/* ___ _ _
/ __| |_ ___ ___ _ _ __| |
| (__| ' \/ -_) -_) '_(_-<_|
\___|_||_\___\___|_| /__(_)
*/
#include "neopixel.h"
#include <math.h>
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D0
#define PIXEL_COUNT 32
#define PIXEL_TYPE WS2812
/* | __| \| |_ _| __| _ \ / __| | /_\ / __/ __|
| _|| .` | | | | _|| / | (_ | |__ / _ \\__ \__ \
|___|_|\_| |_| |___|_|_\ \___|____/_/ \_\___/___/
*/
#define glassID 1
Adafruit_NeoPixel circle = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
//PIXEL_PIN
int pixel_position = 0;
int numberLEDs = 0;
//PRESSURE SENSOR
int fsrPin = A0;
int fsrReading = 0; //measurement
int fluidLevel = 3400;
int fillStatus = 0;
int fillThreshold = 3730;
int glassPresentThreshold = 3200;
int glassPresent = 0;
const int publishRate = 500;
int currPubRate = 500;
//OTHER GLASS
int otherGlassFluidLevel = 3400;
int otherFillStatus = 0;
int otherGlassPresent = 0; //initially assume other glass is present
//SPEAKER
int speakerPin = D1;
int val;
int melody[] = {622,698,800};
int noteDurations[] = {8,8,4};
// Track if the clink is playing
boolean isPlaying = false;
int clinkPlayCount = 0;
void setup() {
Serial.begin( 9600 );
circle.setBrightness(10);
circle.begin();
// Initialize all pixels to 'off'
circle.show();
Particle.variable("DebugMe",&fsrReading,INT);
Particle.variable("DebugThem",&otherGlassFluidLevel,INT);
pinMode(fsrPin,INPUT_PULLUP); // sets pin as input
//subscribe to event according to which glass
if(glassID == 1) {
Particle.subscribe("diot2017Clink2",receiveClink,"35002b001051353338363333"); //Nick
}
if(glassID == 2) {
Particle.subscribe("diot2017Clink1",receiveClink, "3d0050000f51353338363333"); //Marco
}
}
void loop() {
//'Cheers' is activated by placing glass 1 (or 2) with filled liquid level (x) exerted on pressure sensor
// so sensor reads above normal weight for just the glass
fsrReading = analogRead(fsrPin); // pressure
//Serial.println(fsrReading);
//from testing
fluidLevel = -0.0096*(fsrReading*fsrReading) + (2.6435*fsrReading) + 3679.1;
//check present and unfilled
if(fsrReading >= glassPresentThreshold && glassPresent == 0) {
glassPresent = 1;
}
//check if filled
if(fsrReading >= fillThreshold && glassPresent == 1) {
if(fillStatus == 0) {
fillStatus = 1;
announceCheers();
Serial.println("1");
}
if(currPubRate >= publishRate) {
currPubRate = 0;
announceCheers();
Serial.println("2");
}
currPubRate++; //control publish rate when filled
}
//check if lifted
if(fsrReading < glassPresentThreshold && glassPresent == 1) {
glassPresent = 0;
//filled and lifted
if(fillStatus == 1) {
announceCheers();
Serial.println("3");
}
}
//unfilled, glass present
if(fsrReading < fillThreshold && (fsrReading >= glassPresentThreshold || glassPresent == 1) && fillStatus == 1) {
fillStatus = 0;
announceCheers();
Serial.println("5");
}
// The neo pixel does a color chase to alert glass 2 (or 1) the social drink has started
if(otherFillStatus == 1) {
if(fillStatus == 0) {
//you have not filled glass, and other raised his glass
if(otherGlassPresent == 0) {
if(clinkPlayCount == 0)
{
delay(1000);
clink();
clinkPlayCount++;
}
breathe(); //breathe if other guy lifts glass
} else {
breathe();
//colorchase(); // alerts glass if not lifted
}
} else { //both filled
if(clinkPlayCount == 0) {
delay(1000);
clink();
clinkPlayCount++;
}
breathe();
//fluidlevelLED();//TODO show level
}
}
delay(100);
//scanner(90,90, 90, 20);
}
void receiveClink(const char *event, const char *data)
{
otherGlassFluidLevel = atoi(data);
if (otherGlassFluidLevel >= fillThreshold) {
otherFillStatus = 1;
} else {
if(otherGlassFluidLevel > glassPresentThreshold)
{ otherFillStatus = 0;
otherGlassPresent = 1;
} else {
otherGlassPresent = 0;
}
}
}
void announceCheers()
{
//anounce clink to the other device
if(glassID == 1) {
Particle.publish("diot2017Clink1",String(fsrReading)); //Marco
}
if(glassID == 2) {
Particle.publish("diot2017Clink2",String(fsrReading)); //Nick
}
}
void colorchase()
{
//continue loop until I fill glass or other finishes
for(int i=0; i< circle.numPixels(); i++) {
uint32_t c;
if(pixel_position == i) {
c = circle.Color(255, 255, 255);
} else {
c = circle.Color(0, 0, 0);
}
circle.setPixelColor(i, c);
circle.show();
delay(50);
}
//stop color chase
//delay(500);
for(int i = 0; i< circle.numPixels(); i++) {
pixel_position++;
if(pixel_position >= circle.numPixels()) {
pixel_position = 0;
}
circle.show();
//delay(10);
}
//delay(100);
}
/* Calc the sin wave for the breathing white led */
void breathe() {
float val = (exp(sin(millis()/2000.0*M_PI)) - 0.36787944)*108.0;
Serial.println( val );
uint16_t i;
uint32_t c = circle.Color(val, val, val);
for(i=0; i< circle.numPixels(); i++) {
circle.setPixelColor(i, c );
}
circle.show();
delay(50);
numberLEDs = circle.numPixels();
}
// "Larson scanner" = Cylon/KITT bouncing light effect
void scanner(uint8_t r, uint8_t g, uint8_t b, uint8_t wait)
{
int i, j, pos, dir;
pos = 0;
dir = 1;
for(i=0; i<((circle.numPixels()-1) * 8); i++) {
// Draw 5 pixels centered on pos. setPixelColor() will clip
// any pixels off the ends of the circle, no worries there.
// we'll make the colors dimmer at the edges for a nice pulse
// look
circle.setPixelColor(pos - 2, circle.Color(r/4, g/4, b/4));
circle.setPixelColor(pos - 1, circle.Color(r/2, g/2, b/2));
circle.setPixelColor(pos, circle.Color(r, g, b));
circle.setPixelColor(pos + 1, circle.Color(r/2, g/2, b/2));
circle.setPixelColor(pos + 2, circle.Color(r/4, g/4, b/4));
circle.show();
delay(wait);
// If we wanted to be sneaky we could erase just the tail end
// pixel, but it's much easier just to erase the whole thing
// and draw a new one next time.
for(j=-2; j<= 2; j++)
circle.setPixelColor(pos+j, circle.Color(0,0,0));
// Bounce off ends of circle
pos += dir;
if(pos < 0) {
pos = 1;
dir = -dir;
} else if(pos >= circle.numPixels()) {
pos = circle.numPixels() - 2;
dir = -dir;
}
}
}
void fluidlevelLED()
{
//continue loop until I fill glass or other finishes
while(fillStatus == 0 && otherGlassFluidLevel > 10) {
for(int i=0; i< circle.numPixels() - fluidLevel; i++) {
uint32_t c;
if(pixel_position < i) { //|| pixel_position == i-1) {
c = circle.Color(255, 255, 255);
} else {
c = circle.Color(0, 0, 0);
}
circle.setPixelColor(i, c);
}
//stop color chase
circle.show();
//delay(500);
pixel_position++;
if(pixel_position >= circle.numPixels()) {
pixel_position = 0;
}
delay(50);
}
//delay(100);
}
void clink()
{
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 3; thisNote++) {
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
tone(speakerPin, melody[thisNote],noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(speakerPin);
}
}
Click to Expand
Content Rating
Is this a good/useful/informative piece of content to include in the project? Have your say!
You must login before you can post a comment. .