Introduction: Sol Mate

SOL MATE is a project submission for the 2015 IoT Intel Roadshow of Santa Monica.

SOL MATE is a portable and interactive technology that can sense your UV level intake, outdoor temperature, and personal body temperature. There is also a customizable setting of 1-100% of UV exposure that correlates with time for the session of use. In addition, there is a reset button, a Buzzer to notify napping beach-goers when the time is up, and an LCD screen as an interface for the user.

First, the user would set the rotary knob to the exact percentage of UV exposure or tanning for the day. Throughout the day, the user can check the UV levels, outdoor temperature, and personal body temperature to ensure good environmental and body levels. After the sun session is complete, the Buzzer will sound, you will get a text SMS and the LCD screen will show if you’d like to tweet your Sol session.

1. Set up explain the hardware

2. Listing all code to get data from sensors

3. Python - uploading code to twitter

4. Entire structure of the Arduino code

5. 3D print the top

Step 1: Materials and Setting Up the Hardware

Gather the following materials:
1. Grove Starter Kit Plus - Intel IoT Edition
2. Intel Edison Board

3. Base Shield v2

4. Arduino development IDE

5. Wifi 

6. Computer 



Here are the sensors that will be used:

A0: Rotary Angle
A1: Temperature
A2: Infrared Temperature
A3: UV Sensor
D7: Button
D8: Buzzer
I2C: LCD RGB Backlight



You will first need to go to Intel’s Edison website (link) to download their guide in order to go through these steps.

Step 2: Sensors and Other I/O Components

Go to the Arduino IDE. At the beginning, we need to add the board corresponding to the Intel Edison. We choose the port that starts with /dev/cu.usbmodem… Next, we need to set up the pins of I/O pins.
Here are the codes for each component:

Potentiometer:

const int pinRot = A0;
//to read the tan percentage
int rotread = analogRead(pinRot);
tanperc = rotread * 100 / 1015; //the total is 1015 instead of 1024 so that 100% is achievable.

Temperature sensor:

const int pinTemp = A1;
//to read the temperature
int tempread = analogRead(pinTemp);
float res = (float)(1023-tempread)*10000/tempread;
float temp = 1/(log(res/10000)/tempref+1/298.15)-273.15;
temp = temp*1.8 + 32;

UV sensor:

const int pinUV = A3;
//to read the UV index
float uv = analogRead(pinUV);
uv = uv * 4980.0/1023.0 * 0.307 / 200.0;

from the above code of UV, (4980.0/1023.0) is the conversion factor to get voltage value in mV, and 0.307 is the conversion factor to get illumination. Dividing that by 200 gives us the UV index. This is documented on http://www.seeedstudio.com/wiki/Grove_-_UV_Sensor...

Button:

const int pinBut = 7;
//setup
pinMode(pinBut, INPUT);
digitalWrite(pinBut, HIGH); //enable pull up for the pin
//wait for the button to be clicked once
while (!digitalRead(pinBut));
while (digitalRead(pinBut));

Buzzer:

const int pinBuz = 8;
//setup pinMode(pinBuz, OUTPUT);
//buzz it
digitalWrite(pinBuz, HIGH);

LCD:

#include "rgb_lcd.h"
//global variable
rgb_lcd lcd;
//setup
lcd.begin(16, 2);
//set to white
const int white[] = {255, 255, 255};
lcd.setRGB(white[0], white[1], white[2]);
//print welcoming message
lcd.clear(); //clear the display
lcd.setCursor(0, 0); //point to top left corner
lcd.print("Hello, I'm your");
lcd.setCursor(0, 1); //point to bottom left corner lcd.print("Solmate :)");

IR Temperature Sensor:

Go to http://www.seeedstudio.com/wiki/Grove_-_Infrared_...
Add to the beginning:
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define INTERNAL1V1 2
#define INTERNAL2V56 3
#else
#define INTERNAL 3
#endif

Change the following values to make sure the parameters are correct
#define SUR_TEMP_PIN A2 // Analog input pin connect to temperature sensor SUR pin
#define OBJ_TEMP_PIN A3 // Analog input pin connect to temperature sensor OBJ pin
float temp_calibration=-40; //this parameter was used to calibrate the temperature
float temperature_range=30; //we make a map of temperature-voltage according to sensor datasheet.
//10 is the temperature step when sensor and object distance is 9CM.
float offset_vol=-0.387;
//this parameter was used to set the mid level voltage,when put the sensor in normal environment after 10 min,
//the sensor output 0.For example,the surrounding temperature is 29℃,but the result is 27℃ via the sensor,
//you should set the reerence to 0.520 or more,according to your sensor to change.
//the unit is V

Step 3: Python - Uploading Code to Twitter

to get pip, you will need to wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py

After that, you can pip installl a few packages with pip install PACKAGENAME such as python-twitter and smtplib

Run the following python code to send twitter messages from you Solmate.

import twitterimport randomimport timefrom datetime import datetimeimport smtplibimport argparsedef sendMess(percentIn,e,t,u): CLIENT_ID = "1290d6798b1a4e9" sender = "troop138wu@gmail.com" eRecievers= ["6262413103@tmomail.net"] if(percentIn<0 or percentIn>100): print 0 return elif (percentIn<=20): messageIn="Keep calm and get your tan on. Remember to use an SPF!" tweet(1,e,t,u) elif (percentIn<=40): messageIn="Time to soak up the sun! The sun is high, and the tan is low." tweet(2,e,t,u) elif (percentIn<=60): messageIn="Sunscreen is recommended for toaster oven conditions." tweet(3,e,t,u) elif (percentIn<=80): messageIn="You're now equivalent to a baked potato." tweet(4,e,t,u) else: messageIn="You're fried chicken status. Time to go home for the day." tweet(5,e,t,u) try: #print "Sending message to " + recvname + "...", server = smtplib.SMTP(host='smtp.gmail.com',port=587) username = 'troop138wu@gmail.com' password = 'Wu123456' server.ehlo() server.starttls() server.login(username,password) server.sendmail(sender, eRecievers,"From: " +"in"+ "\n"+"To: " +"out"+ "\n"+"Subject: " + "SOLMATE!"+ "\n"+messageIn) server.quit() print "successfully sent!" except Exception: print "Error: unable to send message" print 1def tweet(choice,e,t,u): tweets=['Happy to soak up the sunlight for the day!','I know #Solmate always has my back for getting a perfect tan.','Safely getting a healthy amount of UV rays for the day!','Having fun under the sun. Make sure to wear some shades and sunscreen!','I just got my daily dose of Vitamin D and Calcium'] api = twitter.Api(consumer_key='d6RF46ZYRC1EMJ9GFfhwAsPHo', consumer_secret='syq9klXBYYQbAnSVm6ie3qPpi2PFtO2nwQI0nEdsYMWxDGIUgJ', access_token_key='3246491366-V2KQG7EF1R6rAFZv4GCsZLw8kEZOuXHaUUEUq1n', access_token_secret='5nPvjXaJscb8wqKH32RSy3jTrA4VnP9PPJxvesG8Q3NIg') choice=tweets[choice-1]+' #'+e+'mins #'+t+'F #uv'+u+' #SolMate #IntelMaker' try: status = api.PostUpdate(choice) except: choice+=' #'+(str(datetime.now()))[:10]+' #'+str(int((str(datetime.now()))[11:13])-7)+(str(datetime.now()))[13:19] status = api.PostUpdate(choice) return status.textif __name__ == "__main__": parser = argparse.ArgumentParser(description="send message and tweets") parser.add_argument('-m', '--message', dest='mess', help='message') parser.add_argument('-e', '--e', dest='e', help='elapsed time') parser.add_argument('-t', '--t', dest='t', help='temperature') parser.add_argument('-u', '--u', dest='u', help='uv') args = parser.parse_args() mess=int(args.mess) sendMess(mess,args.e,args.t,args.u)

Step 4: Entire Structure of the Arduino Code

#include
#include "rgb_lcd.h" #include #include

rgb_lcd lcd;

const int white[] = {255, 255, 255}; const int red[] = {255, 0, 0};

const int pinRot = A0; const int pinTemp = A1; const int pinIR = A2; const int pinUV = A3;

const int pinBut = 7; const int pinBuz = 8;

const int tempref = 3975;

int statecount = 0; int tanperc = 0; int tantarg = 0; float alltemp[8] = {0, 0, 0, 0, 0, 0, 0, 0}; //float allIR[8] = {0, 0, 0, 0, 0, 0, 0, 0}; float alluv[8] = {0, 0, 0, 0, 0, 0, 0, 0}; int pt = 0; float acctemp = 0; //float accIR = 0; float accUV = 0; float exposure = 0; const int displayrate = 40; const int burnrate = 170;

int maxuv = 0; int maxtemp = 0; unsigned long starttime = 0; unsigned long endtime = 0;

void setup() { Serial.begin(9600); lcd.begin(16, 2); lcd.setRGB(white[0], white[1], white[2]); lcd.setCursor(0, 0); lcd.print("Hello, I'm your"); lcd.setCursor(0, 1); lcd.print("Solmate :)"); pinMode(pinBut, INPUT); digitalWrite(pinBut, HIGH); pinMode(pinBuz, OUTPUT); statecount = 0; delay(4000); setTan(); }

void clrRow(int row) { lcd.setCursor(0, row); lcd.print(" "); }

void setTan() { lcd.setRGB(white[0], white[1], white[2]); lcd.setCursor(0, 0); lcd.print("Set your tan %! "); clrRow(1); while (!digitalRead(pinBut)) { int rotread = analogRead(pinRot); tanperc = rotread * 100 / 1015; tantarg = rotread * burnrate / 1015; char perc[] = "100%"; int targ = tanperc; for (int i = 2; i >= 0; i--) { if (i < 2 && targ == 0) { perc[i] = ' '; } else { perc[i] = '0' + targ%10; } targ /= 10; } lcd.setCursor(6, 1); lcd.print(perc); delay(100); } exposure = 0; while (digitalRead(pinBut)); lcd.clear(); starttime = millis(); maxuv = 0; maxtemp = 0; }

boolean readFile(){ //Get the query result from file char data[16]; FILE *fp; fp = fopen("/tmp/tantweet.txt", "r"); if(fp!=NULL){ fgets(data, 16, fp); fclose(fp); if (data[0] == '1') return true; else return false; }else{ return false; } }

void tanned() { endtime = millis(); lcd.setRGB(red[0], red[1], red[2]); clrRow(0); clrRow(1); lcd.setCursor(0, 0); lcd.print("Perfectly tanned!"); digitalWrite(pinBuz, HIGH); delay(500); digitalWrite(pinBuz, LOW); delay(500); digitalWrite(pinBuz, HIGH); delay(500); digitalWrite(pinBuz, LOW); delay(500); digitalWrite(pinBuz, HIGH); delay(500); digitalWrite(pinBuz, LOW); delay(500); lcd.setRGB(white[0], white[1], white[2]); clrRow(0); lcd.setCursor(0, 0); lcd.print("Tweet it?"); int tweet = 0; while (!digitalRead(pinBut)) { //select yes or no int rotread = analogRead(pinRot); lcd.setCursor(0, 1); if (rotread < 512) { lcd.print(" >Yes No "); tweet = 1; } else { lcd.print(" Yes >No "); tweet = 0; } delay(100); } while (digitalRead(pinBut)); if (tweet == 1) { String cmd = "python /home/root/test7.py -m "; cmd = cmd + tanperc + " -e "; cmd = cmd + ((endtime-starttime)/60000) + " -t "; cmd = cmd + maxtemp + " -u "; cmd = cmd + maxuv + " > /tmp/tantweet.txt"; //Excute the query, and get the result system(cmd.buffer); lcd.clear(); if (readFile()) { lcd.setRGB(white[0], white[1], white[2]); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Tweeted!"); } else { lcd.setRGB(white[0], white[1], white[2]); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Failed to"); lcd.setCursor(0, 1); lcd.print("tweet..."); } delay(4000); } }

void loop() { Serial.println("hello"); //check if finished if (exposure >= tantarg) { tanned(); setTan(); } else { //check if reset if (digitalRead(pinBut)) { while (digitalRead(pinBut)); setTan(); } }

//update all sensor inputs //temperature int tempread = analogRead(pinTemp); float res = (float)(1023-tempread)*10000/tempread; float temp = 1/(log(res/10000)/tempref+1/298.15)-273.15; temp = temp*1.8 + 32; acctemp += temp - alltemp[pt]; alltemp[pt] = temp; Serial.print("temp:"); Serial.println(temp); //UV float uv = analogRead(pinUV); uv = uv * 4980.0/1023.0 * 0.307 / 200.0; accUV += uv - alluv[pt]; alluv[pt] = uv; Serial.print("uv:"); Serial.println(accUV/8); pt = (pt < 7? pt+1 : 0); //output data every 0.5 sec if (statecount % 10 == 0) { if (acctemp/8 > maxtemp) { maxtemp = (acctemp/8); } if (accUV/8 > maxuv) { maxuv = (accUV/8); } if (statecount < displayrate ) { //temperature char buffer[16]; sprintf(buffer, "Temp %0.1f F", acctemp/8); clrRow(0); lcd.setCursor(2, 0); lcd.print(buffer); } else { //UV char buffer[16]; sprintf(buffer, "UV Index %0.1f", accUV/8); clrRow(0); lcd.setCursor(2, 0); lcd.print(buffer); } //update tan lcd.setCursor(0, 1); for (int i = 0; i < 16 * exposure / tantarg; i++) { lcd.print("X"); } } exposure += uv/600; statecount = (statecount < 2*displayrate? statecount+1 : 0); delay(100); }

Step 5: Package the Electronics

Package your electronics in an oversize beverage container so that you can place it in the cup holder of a beach chair.

3D print a beverage container lid to mount the controls and sensors by downloading the following stl file.

Mount your displays and sensors into your lid using the diagram above.

1: Button

2: UV Sensor

3: Rotary Angle Knob

4: Temperature Sensor

5: Straw for mounting Infrared Temperature Sensor

6: Humidity Sensor

7: Misc

8: Place over Rotary Angle Knob

Step 6: Finished Product

Summer Fun Contest

Participated in the
Summer Fun Contest