Twitter icon
Facebook icon
LinkedIn icon
Google icon
Reddit icon
StumbleUpon icon
Del.icio.us icon

SolBox

Added to IoTplaybook or last updated on: 09/02/2019

SolBox

Overexposure to the sun is the leading preventable cause of skin aging, wrinkles, and skin cancer. Skin cancer rates have increased over the last three decades, with the fair-skinned population in China and the US being the most at-risk for development of skin disease from exposure to ultraviolet B (UVB) rays. The most effective preventative measure is the most simple-- apply sunscreen and limit long hours of direct exposure under the sun. However, a recent study shows that the sunscreen usage rate is shockingly low with rates around 21.3% among college-aged Chinese students. 

Click to go to YouTube and watch introductory video

But how can you be more informed about how much sunlight is too much? This is the question we're set out to answer with SolBox. SolBox is an easy to use yet powerful device that will notify you when you're in danger of skin damage from the sun's rays.

SolBox
1 / 4 - 3D model

SolBox
2 / 4

SolBox
3 / 4

SolBox
4 / 4

Here's how it works: You first set up your profile using the simple user interface on the SolBox app. This is where you'll tell us important information such as your age, skin color, patterns of exposure to sunlight, etc.

 

SolBox
Personalized background data for custom thresholds

 

Fitzpatrick scale is the most commonly used classification of a person’s skin type.
Fitzpatrick scale is the most commonly used classification of a person’s skin type.

Then, using our algorithm backed by comprehensive scientific research, we'll determine your thresholds for sun exposure risks at various UV intensity level and time intervals. That's it! To use SolBox, simply take it with you when you go to the pool, backyard BBQ, or wherever you'll be in sunlight. Just turn on SolBox and we'll do the rest. SolBox will constantly monitor the sun's UV rays in real-time and notify you via the SolBox app and built-in speaker when it's time to reapply sunscreen or take cover under some shade.

Notifications are announced via the SolBox speaker and/or the mobile app.
Notifications are announced via
the SolBox speaker and/or the mobile app.

The speaker on SolBox is also capable of Bluetooth connectivity so you can use it play your favorites tunes! Notifications from SolBox, spoken in English and Mandarin, will temporarily pause your music. Your music will automatically resume after the notification.

Live Data and Historical Data
Live Data and Historical Data

Things used in this project

Hardware components

ELEGOO UNO R3 Project Complete Starter Kit
ELEGOO UNO R3 Project Complete Starter Kit
Specific components used from the starter kit were the Arduino Uno, LCD panel, Rotary Encoder, Temperature/Humidity sensor, resistors, wires, and 10k potentiometer.
× 1

Buy

 
WaveShare UV Sensor
 
× 1

Buy

 
HiLetgo Micro SD TF Card Adapter
 
× 1

Buy

 
LM386 Audio Amplifier Module
 
× 1

Buy

 
Bluetooth speaker
To enable the Bluetooth functionality we hacked a cheap Bluetooth speaker we received from an event. We opened up the Bluetooth speaker and cut the wires from the printed circuit board to the speaker which left us with a speaker component and a Bluetooth enabled printed circuit board.
× 1  
ELEGOO Neptune FDM 3D Printer
ELEGOO Neptune FDM 3D Printer
 
× 1

Buy

 
Aideepen ESP8266 Serial Wi-Fi Wireless ESP-01 Adapter Module
 
× 1

Buy

 
Relay Module (Generic)
 
× 2  
 
Micro SD Card
 
× 1

Buy

Software apps and online services

Arduino IDE
Arduino IDE
 
  Link

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
 
   
Solder Wire, Lead Free
Solder Wire, Lead Free
 
 

Buy

Building Instructions

Components used in Solbox.
Components used in Solbox

1. Connect the circuit according to the circuit diagram. The circuit diagram tells you where each component pin should connect to the Arduino.

2. Download the sound files and save them to your SD card. These are the alerts that will play when the user needs to apply sunscreen and when the user needs to get out of the sun or risk skin damage. The current recorded messages are "Time to apply sunscreen" and "Too much sun, time to go inside", recorded in both English and Mandarin. If you would like to record your own sound files you will need to make sure they are the correct format. They should be wav files formatted with 8-bit resolution, 16000 Hz sampling rate, mono audio channel, and PCM unsigned 8-bit. You can use an online audio converter to get the right format https://audio.online-convert.com/convert-to-wav.

Online audio converter tool
Online audio converter tool

3. Connect the Arduino Uno to your host computer.

4. Copy the code into a new sketch.

5. Download additional libraries by going to Tools > Manage Libraries. You will need to search for and install the "DHT sensor library by Adafruit", "Audio by Arduino", and "TMRpcm by TMRh20". Without the libraries you will get compiler errors.

Download additional libraries
Download additional libraries

6. Deploy the sketch.

7. Once deployed the LCD screen should start to light up but it may be difficult to read the text. Toggle the 10k potentiometer until you can read the text clearly.

8. The audio from the speaker might be quiet, to adjust the volume turn the potentiometer built into the audio amplifier.

Component Assembly

Components to fit with the 3D-printed cover:

LCD, Rotary Dial, pin hole for UV sensor fit inside the 3D printed cover
LCD, Rotary Dial, pin hole for UV sensor fit inside the 3D printed cover

 

Top components are fitted and assembled into the 3D printed cover.
Top components are fitted and assembled into the 3D printed cover.

Core components, placed under the cover components:

The Arduino, Wifi module, SD card reader, temperature & humidity sensor are under the top cover components.
The Arduino, Wifi module, SD card reader, temperature & humidity sensor
are under the top cover components.

Charging and Bluetooth modules:

The Bluetooth board, battery and relays will be placed under. There is a hole for the charging port for the battery on the side of the 3D model.
The Bluetooth board, battery, and relays will be placed under.
There is a hole for the charging port for the battery on the side of the 3D model.

Bottom speaker:

The speaker will be placed at the very bottom.
The speaker will be placed at the very bottom

Arduino Code and Circuit Diagrams

Please see Attachments for Arduino code and circuit diagrams.

Team Background

Dathan Wong - B.S. Electrical Engineering, minor Computer Science

Chia-Chun Chen - University of California Los Angeles (UCLA) PhD candidate in Medical and Molecular Pharmacology, research interest in skin cancer 

Kevin Vo - Database/Business Intelligence Developer

Grace Han - Program Manager

Sarah Han - Software Engineer, B.F.A. Graphic Design, minor Computer Science, minor Web Technologies and Applications

Custom parts and enclosures

SolBox - top lid

Cover for the box, placement for LCD screen, UV sensor, rotary knob - Download

SolBox

 

SolBox - bottom container

Holds all of the electronics (sensors, Arduino, wires, breadboards) - Download

SolBox

Schematics

SolBox Circuit Diagram - Download

Connect the different components to the Arduino Uno as described in the document. This is not a traditional circuit diagram but hopefully is easier to follow for anyone new to electronics.

Sound Files - Download

Unzip the sound files folder and copy the files to your SD card.

Code

SolBox Code - Arduino - Download

The following code will run on the Arduino Uno. The wav files must be formatted with 8 bit resolution, 16000 Hz sampling rate, mono audio channel, and PCM unsigned 8-bit. You can use an online audio converter to get the right format https://audio.online-convert.com/convert-to-wav. The current version collects data every second but can be changed by editing the readInterval variable in milliseconds.

 

#include "DHT.h" 
#include "LiquidCrystal.h" 
#include "SD.h" 
#include "SPI.h" 
#include "TMRpcm.h" 
#include "SoftwareSerial.h" 
 
//Calculations 
unsigned long readInterval = 1000; 
unsigned long elapsedTime = 0; 
unsigned long newTime; 
unsigned long oldTime = 0; 
unsigned int skinTone = 999; 
unsigned int skinType[] = {166, 200, 266, 333, 533, 1000}; 
double averageUV = 0; 
double timeAllowed; 
boolean sunscreenAlert = false; 
boolean insideAlert = false; 
 
//Wifi 
SoftwareSerial mySerial(0,1); 
 
//SD card 
#define SD_ChipSelectPin 4  
TMRpcm speaker; 
 
//Temperature Sensor 
#define DHTPIN 6 
#define DHTTYPE DHT11 
DHT dht(DHTPIN, DHTTYPE); 
 
//UV Sensor 
const int pinUV = A0; 
float uv; 
int uvIndex; 
 
//LCD Display 
LiquidCrystal lcd(A1, A2, A3, A4, A5, 5); 
 
//Rotary Encoder 
enum PinAssignments{ 
  encoderPinA = 2, encoderPinB = 3, clearButton = 10 
}; 
volatile unsigned int encoderPos = 1; 
unsigned int lastReportedPos=1; 
static boolean rotating=false; 
boolean A_set = false; 
boolean B_set = false; 
unsigned int maxSkinTone = 6; 
 
//Speaker 
#define RELAYPIN 7 
#define SPKPIN 9 
 
void setup() { 
  Serial.begin(9600); 
   
  //Temperature/Humidity Sensor 
  dht.begin(); 
   
  //LCD Display 
  lcd.begin(16,2); 
  lcd.print("Set skin tone"); 
  lcd.setCursor(0,1); 
  lcd.print(encoderPos); 
 
 
  //WiFi 
  mySerial.begin(9600); 
  SendCommand("AT+RST", "Ready"); 
  delay(5000); 
  SendCommand("AT+CWMODE=1","OK"); 
  SendCommand("AT+CIFSR", "OK"); 
  SendCommand("AT+CIPMUX=1","OK"); 
  SendCommand("AT+CIPSERVER=1,80","OK"); 

   
  //Rotary Encoder 
  pinMode(encoderPinA, INPUT_PULLUP); 
  pinMode(encoderPinB, INPUT_PULLUP); 
  pinMode(clearButton, INPUT_PULLUP); 
  attachInterrupt(digitalPinToInterrupt(2), doEncoderA, CHANGE); 
  attachInterrupt(digitalPinToInterrupt(3), doEncoderB, CHANGE); 
   
 
  //Speaker 
  pinMode(RELAYPIN, OUTPUT); 
  digitalWrite(RELAYPIN, LOW); 
  speaker.speakerPin=SPKPIN; 
  if(!SD.begin(SD_ChipSelectPin)){ 
    Serial.print("Failed to initiate SD card"); 
    return; 
  } 
 
  //SD Card 
  if(!SD.begin(SD_ChipSelectPin)){ 
    Serial.println("SD fail"); 
    return; 
  } 
   
 
 
} 
 
void loop() { 
 
    //read sensor values every interval to avoid collecting too much data 
    newTime = millis(); 
    if((newTime - oldTime) > readInterval){ 
      //Read UV sensor input and conversion to UV index 
      //UV index conversion from http://arduinolearning.com/code/arduino-guva-s12sd-uv-sensor.php 
      uv = analogRead(pinUV); 
      if(uv <= 40){ 
        uvIndex = 0; 
      } else{ 
        uvIndex = floor(uv/20)-1; 
      } 
       
      //Read temperature data 
      float temp = dht.readTemperature(); 
 
      //Send data over Wifi 
      mySerial.println("AT+CIPSEND=0,23"); 
      mySerial.println(uvIndex); 
      SendCommand("AT+CIPCLOSE=0","OK"); 
       
      //Calculate average UV exposure 
      elapsedTime++; 
      oldTime = newTime; 
      averageUV = (((elapsedTime - 1) * averageUV) + uvIndex)/elapsedTime; 
 
       
       
      //Calculate times 
      if(skinTone <= maxSkinTone){ 
        timeAllowed = (skinType[skinTone-1] / averageUV) * 60000; 
        //Time to apply sunscreen 
        if (((timeAllowed/2) < (elapsedTime * readInterval)) && !sunscreenAlert){ 
          lcd.clear(); 
          lcd.print("Sunscreen time"); 
          sunscreenAlert = true; 
          //Play from SD card 
          digitalWrite(RELAYPIN, HIGH); 
          speaker.play("4.wav"); 
          delay(3000); 
          speaker.play("2.wav"); 
          delay(3000); 
          digitalWrite(RELAYPIN, LOW); 
        } 
        //Time to go inside 
        if ((timeAllowed < (elapsedTime * readInterval)) && !insideAlert){ 
          lcd.clear(); 
          lcd.print("Time to go inside"); 
          insideAlert = true; 
          //Play from SD card 
          digitalWrite(RELAYPIN, HIGH); 
          speaker.play("3.wav"); 
          delay(3000); 
          speaker.play("1.wav"); 
          delay(3000); 
          digitalWrite(RELAYPIN, LOW); 
        } 
      } 
       
      //Output for debugging 
      Serial.print("UV Index: "); 
      Serial.print(uvIndex); 
      Serial.print(" UV Value: "); 
      Serial.print(uv); 
      Serial.print(" Temp: "); 
      Serial.print(temp); 
      Serial.print(" Average UV: "); 
      Serial.print(averageUV); 
      Serial.print(" Elapsed Time: "); 
      Serial.print(elapsedTime); 
      Serial.print(" Time Allowed: "); 
      Serial.print(timeAllowed); 
      Serial.println(); 
    } 
     
    //Rotary Encoder 
    if(skinTone > 6){ 
      rotating = true; 
      //Print skin tone selection 
      lcd.setCursor(0,1); 
      if(lastReportedPos != encoderPos){ 
        if(lastReportedPos >= 10){ 
          lcd.clear(); 
          lcd.setCursor(0,0); 
          lcd.print("Set skin tone"); 
          lcd.setCursor(0,1); 
        } 
      lcd.print(encoderPos); 
      lastReportedPos = encoderPos; 
      } 
      //Select skin tone 
      if(digitalRead(clearButton) == LOW){ 
        lcd.clear(); 
        skinTone = encoderPos; 
        elapsedTime = 0; 
        lcd.print("Monitoring Skin"); 
      } 
    } 
     
} 
 
 
void doEncoderA(){ 
  if(rotating) delay(1); 
  if(digitalRead(encoderPinA)!=A_set){ 
    A_set=!A_set; 
    if(A_set && !B_set){ 
      encoderPos++; 
      if (encoderPos > maxSkinTone) encoderPos = 1; 
      rotating = false; 
    } 
  } 
} 
 
void doEncoderB(){ 
  if(rotating) delay(1); 
  if(digitalRead(encoderPinB) != B_set){ 
    B_set = !B_set; 
    if(B_set && !A_set){ 
      encoderPos--; 
      if (encoderPos == 0) encoderPos = maxSkinTone; 
      rotating = false; 
    } 
  } 
} 
 

boolean SendCommand(String cmd, String ack){ 
  mySerial.println(cmd); 
  if (!echoFind(ack)) return true; 
} 
 
boolean echoFind(String keyword){ 
 byte current_char = 0; 
 byte keyword_length = keyword.length(); 
 long deadline = millis() + 5000; 
 while(millis() < deadline){ 
  if (mySerial.available()){ 
    char ch = mySerial.read(); 
    Serial.write(ch); 
    if (ch == keyword[current_char]) 
      if (++current_char == keyword_length){ 
       Serial.println(); 
       return true; 
    } 
   } 
  } 
 return false; // Timed out 
} 

 

Credits

Sarah Han

Sarah Han

6 projects • 32 followers

Software Engineer, Design, 3D

Contact

Grace Han

Grace Han

2 projects • 2 followers

Contact

Kevin Vo

Kevin Vo

2 projects • 1 follower

Contact

Dathan Wong

Dathan Wong

2 projects • 1 follower

Contact

Chia-Chun Chen

Chia-Chun Chen

2 projects • 0 followers

Contact