#include <WiFi.h>
#include "time.h"
#include <Adafruit_NeoPixel.h>
#include "SPI.h"
#define NEO_PIN 21 // Which pin on the Arduino is connected to the NeoPixels?
#define NUMPIXELS 12 // Popular NeoPixel ring size
#define pot180 34
#define pot0 35
#define pot90 32
#define pot270 33
#define Dval 0.5
#define BTNstart 25
#define ymin 0
#define xmax 1
#define ymax 2
#define xmin 3
#define testLED 27
// ------------------74HC595 SIPO LED Driver---------------
#define latchPin_SIPO 15 // ST_CP pin 12
#define clockPin_SIPO 2 // SH_CP pin 11
#define dataPin_SIPO 4 // DS pin 14
uint8_t laser595;
uint8_t tof595;
int tofRead[4]; // hole the readings from the sensors
int ledPos[4]={0,3,6,9}; //positions of the 0, 90, 180 and 270 pixels
int TOFaddress[8]={0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35};
#define debugmode 1 //are we sending data out of the Serial Port
//Vars that will be updated from the database
boolean showPegSecs=0; //are we showing the seconds on the pegs?
byte colours[5][3]={{0,0,0}, //0 -OFF
{0,255,0}, //1 Green
{255,0,0}, //2 Red
{255,165,0}, //3 Orange
{255,255,255} //4 White
};
#define cBlack 0
#define cGreen 1
#define cRed 2
#define cOrange 3
#define cWhite 4
int NTPrefresh=1; //how many mins before we request the NTP time again. // refreshed from database
unsigned long miliStart;
byte STATUS_bootsequence=0;
byte TMRsecs;
byte TMRmins;
byte TMRhrs;
byte NTPcount;
byte doNTPRefresh; //this is just a flag
const char * ssid="Wokwi-GUEST";
const char * wifipw="";
// ------------------Neopixel Driver---------------
Adafruit_NeoPixel pixels(NUMPIXELS, NEO_PIN, NEO_GRB + NEO_KHZ800);
void setup(){
byte sens;
int lp;
int ilp;
STATUS_bootsequence=1; //we are in the boot sequence
Serial.begin(115200);
Serial.setDebugOutput(true);
pinMode(BTNstart,INPUT);
pinMode(latchPin_SIPO, OUTPUT);
pinMode(clockPin_SIPO, OUTPUT);
pinMode(dataPin_SIPO, OUTPUT);
pinMode(testLED, OUTPUT);
Serial.println("in");
// laser595 = 0b00000000;
// tof595=0b00000000;
// for (sens=7;sens>0; sens--) {
// bitWrite(tof595,sens,1);
// write595(tof595,laser595);
// delay(100);
// }
//write595(tof595,laser595);
//initTime("GMT0BST,M3.5.0/1,M10.5.0"); // Set for London UK
//getNTPTime(); //Setup the time
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.clear(); // Set all pixel colors to 'off'
miliStart=millis(); //Flag for screen / LED refresh
doNTPRefresh=false;
//theaterChase(pixels.Color(127, 127, 127), 50); // White
lightUp();
}
void loop() {
// //if (STATUS_bootsequence==1) {
// do {
// readSensors(true);
// } while (digitalRead(BTNstart)==0);
// Serial.println("Ready");
// // }
// STATUS_bootsequence=2;
// doLogic();
}
void Arrow(int endpoint) {
byte numberOfTrails=4;
byte lp;
byte op;
int spoint1;
int spoint2;
int point1;
int point2;
uint32_t color=pixels.Color(0, 255, 0);
for (op=0;op<5;op++) {
spoint1=endpoint+numberOfTrails;
spoint2=endpoint-numberOfTrails;
point1=spoint1+1;
point2=spoint2-1;
pixels.clear(); // Set all pixels in RAM to 0 (off)
for (lp=0; lp<=numberOfTrails;lp++) {
point1=checkPoint(point1,0);
point2=checkPoint(point2,0);
//Serial.print(String(lp)+","+String(point1)+","+String(point2));
point1--;
point2++;
point1=checkPoint(point1,color);
point2=checkPoint(point2,color);
pixels.show();
//Serial.println(" ,"+String(point1)+","+String(point2));
delay(200);
}
}
}
byte checkPoint(int thisval, uint32_t pcolor) {
if (thisval>11) {thisval=thisval-12;}
if (thisval<0) {thisval=thisval+12;}
pixels.setPixelColor(thisval, pcolor); // Set pixel 'c' to value 'color'
return thisval;
}
void lightUp() {
int lp;
int thiscol;
uint32_t Lcols[6]={pixels.Color(255, 0, 0),
pixels.Color(0,255, 0),
pixels.Color(0, 0, 255),
pixels.Color(255, 255, 255),
pixels.Color(127, 127, 127),
pixels.Color(0, 0, 0)};
pixels.clear();
for (thiscol=0;thiscol<6;thiscol++) {
for (lp=0;lp<12;lp++) {
pixels.setPixelColor(lp, Lcols[thiscol]);
delay(75);
pixels.show();
}
}
}
void write595(uint8_t tofData, uint8_t laserData) {
digitalWrite(latchPin_SIPO, LOW);
shiftOut(dataPin_SIPO, clockPin_SIPO, LSBFIRST, laserData);
shiftOut(dataPin_SIPO, clockPin_SIPO, LSBFIRST, tofData);
digitalWrite(latchPin_SIPO, HIGH);
}
void readSensors(bool disp) {
tofRead[ymin] = analogRead(pot0)/Dval;
tofRead[xmax] = analogRead(pot90)/Dval;
tofRead[ymax] = analogRead(pot180)/Dval;
tofRead[xmin] = analogRead(pot270)/Dval;
if (disp) {
Serial.print(tofRead[ymin]);
Serial.print(",");
Serial.print(tofRead[xmax]);
Serial.print(",");
Serial.print(tofRead[ymax]);
Serial.print(",");
Serial.print(tofRead[xmin]);
Serial.println();
}
}
void doLogic() {
bool flipped=false;
int xLength;
int yLength;
bool redFlags[4];
int lp;
for (lp=0;lp<4;lp++) {
redFlags[lp]=0;
}
readSensors(false);
// tofTemp[ymin]=tofRead[ymin];
// tofTemp[xmax]=tofRead[xmax];
// tofTemp[ymax]=tofRead[ymax];
// tofTemp[xmin]=tofRead[xmin];
yLength=tofRead[ymin]+tofRead[ymax];
xLength=tofRead[xmax]+tofRead[xmin];
if (tofRead[xmax]>2000) {
setColour(xmax,cRed);
redFlags[xmax]=true;
} else if (tofRead[xmax]<=2000) {
setColour(xmax,cGreen);
}
if (tofRead[xmin]>2000) {
setColour(xmin,cRed);
redFlags[xmin]=true;
} else if (tofRead[xmin]<=2000) {
setColour(xmin,cGreen);
}
if (tofRead[ymin]>3000) {
setColour(ymin,cRed);
redFlags[ymin]=true;
} else if (tofRead[ymin]<=3000) {
setColour(ymin,cGreen);
}
if (tofRead[ymax]>3000) {
setColour(ymax,cRed);
redFlags[ymax]=true;
} else if (tofRead[ymax]<=3000) {
setColour(ymax,cGreen);
}
//now do the logic
if ((yLength<=4000) && ((xLength>4000) && (xLength<=5000))) {
//we need to flip.
flipped=true;
}
pixels.show();
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
for(int a=0; a<10; a++) { // Repeat 10 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
pixels.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for(int c=b; c<pixels.numPixels(); c += 3) {
pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
pixels.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
}
void setColour(byte which, int clr) {
uint32_t color;
color=pixels.Color(colours[clr][0],colours[clr][1],colours[clr][2]);
pixels.setPixelColor(ledPos[which], color); // Set pixel 'c' to value 'color'
}
// void loop() {
// int hour_d;
// int min_d;
// int min_r;
// int secs_d;
// int secs_r;
// int h_sat;
// int m_sat;
// int s_sat;
// byte tempHRSid;
// byte tempMINSid;
// boolean showSecs;
// boolean showMins;
// h_sat=255;
// m_sat=255;
// s_sat=255;
// int potValue;
// //lets say that saturation is 255 (eg full), when the seconds are merged also, it is halved.
// if (millis() > miliStart+1000) {
// TMRsecs++;
// if (TMRsecs>59) {
// TMRsecs=0;
// TMRmins++;
// if (TMRmins>59) {
// TMRmins=0;
// TMRhrs++;
// NTPcount++;
// doNTPRefresh=(NTPcount>=NTPrefresh);
// if (NTPcount>24) {NTPcount=0;}
// if (TMRhrs>12) {
// TMRhrs=0;
// }
// }
// }
// Serial.println(String(TMRhrs)+":"+String(TMRmins)+":"+String(TMRsecs));
// hour_d = TMRhrs%12;
// min_d = TMRmins/5;
// min_r = TMRmins%5;
// secs_d=TMRsecs/5;
// secs_r=TMRsecs%5;
// showSecs=true;
// showMins=true;
// tempHRSid=idH; //by default it is the standard index
// tempMINSid=idM; //by default it is the standard index
// if (secs_d==min_d) {
// tempMINSid=idSM; //secs and mins are combined
// showSecs=false; //we dont show the secs as they are under the mins
// }
// if (secs_d==hour_d) {
// tempHRSid=idSH; //secs and hrs are combimes
// showSecs=false; //we dont show the secs as they are under the mins
// }
// if (min_d==hour_d) {
// //if the mins and hours are the same, change the hours index to the right one
// tempHRSid=idMH; //mins and hours combined
// showMins=false; //We dont show the mins as they are under the hrs
// if (min_d==secs_d) {
// tempHRSid=idSMH; //mins, hrs and secs are combined
// showSecs=false; //we dont show the secs as they are under the mins
// }
// }
// pixels.clear();
// setNeoColour(hour_d,tempHRSid);
// Serial.println("Hrs id="+String(tempHRSid));
// if (showMins==true) {
// setNeoColour(min_d,tempMINSid);
// Serial.println("mins id="+String(tempMINSid));
// }
// if (showSecs==true) {
// setNeoColour(secs_d,idS); //no need for a temp as it will only be "standard"
// Serial.println("secs id="+String(idS));
// }
// showModMins(min_r, secs_r);
// pixels.show();
// miliStart=millis();
// }
// STATUS_bootsequence=2; //we have done a loop at least once.
// if (doNTPRefresh) {
// getNTPTime(); //this just tightens up the timers every hour (or so)
// }
// potValue = analogRead(pot180)/Dval;
// Serial.println(potValue);
// }
// void showModMins(int mins, int secs) {
// int lp;
// int minsFlag=0;
// int secsFlag=0;
// int colIndex;
// Serial.print("m="+String(mins)+" s="+String(secs)+" ... ");
// for(lp=1;lp<5;lp++) {
// minsFlag=(mins>=lp);
// secsFlag=(secs==lp);
// //deal with the minutes first.
// colIndex=idO;
// if ((secsFlag==true) && (showPegSecs==true)) {
// colIndex=idM;
// if (minsFlag) { //set it to mix
// colIndex=idSM;
// }
// } else if (minsFlag) {
// colIndex=1; //we know it is only the mins
// }
// setcolour(lp-1,colorMix[colIndex][0],colorMix[colIndex][1],colorMix[colIndex][2]);
// Serial.print(" "+String(minsFlag));
// }
// Serial.println();
// }
// void setcolour(int which, int R, int G, int B) {
// analogWrite(RGBleds[which][0],R);
// analogWrite(RGBleds[which][1],G);
// analogWrite(RGBleds[which][2],B);
// }
// void setNeoColour(int px, int id) {
// pixels.setPixelColor(px, colorMix[id][0],colorMix[id][1],colorMix[id][2]);
// }
// void mixTwoColourIndexes(int idxTarget, int idxA, int idxB) {
// colorMix[idxTarget][0]=(colorMix[idxA][0]/2)+(colorMix[idxB][0]/2);
// colorMix[idxTarget][1]=(colorMix[idxA][1]/2)+(colorMix[idxB][1]/2);
// colorMix[idxTarget][2]=(colorMix[idxA][2]/2)+(colorMix[idxB][2]/2);
// }
// void mixThreeColourIndexes(int idxTarget, int idxA, int idxB, int idxC) {
// colorMix[idxTarget][0]=(colorMix[idxA][0]/3)+(colorMix[idxB][0]/3)+(colorMix[idxC][0]/3);
// colorMix[idxTarget][1]=(colorMix[idxA][1]/3)+(colorMix[idxB][1]/3)+(colorMix[idxC][1]/3);
// colorMix[idxTarget][2]=(colorMix[idxA][2]/3)+(colorMix[idxB][2]/3)+(colorMix[idxC][2]/3);
// }
// void RGBtoindex(int idx, String colourstring, float bright_target) {
// float R;
// float G;
// float B;
// String temp;
// colourstring.toUpperCase();
// if (colourstring=="#FFFFFF") {//it is a special case as NEO says white it 000
// colourstring="#000000";
// }
// R=strToHex(colourstring.substring(1,3));
// G=strToHex(colourstring.substring(3,5));
// B=strToHex(colourstring.substring(5,7));
// Serial.println ("RGB "+String(R)+","+String(G)+","+String(B));
// R=(R/255)*bright_target;
// G=(G/255)*bright_target;
// B=(B/255)*bright_target;
// Serial.println ("RGB after "+String(R)+","+String(G)+","+String(B));
// colorMix[idx][0]= R;//0,2 //2,4 //4,6
// colorMix[idx][1]= G;
// colorMix[idx][2]= B;
// }
// int strToHex(const String src)
// {
// char hexValue[3] ;
// src.toCharArray(hexValue,3);
// Serial.println(hexValue);
// byte tens = (hexValue[0] < '9') ? hexValue[0] - '0' : hexValue[0] - '7';
// byte ones = (hexValue[1] < '9') ? hexValue[1] - '0' : hexValue[1] - '7';
// byte number = (16 * tens) + ones;
// return(number);
// }
// void setTimezone(String timezone){
// Serial.printf(" Setting Timezone to %s\n",timezone.c_str());
// setenv("TZ",timezone.c_str(),1); // Now adjust the TZ. Clock settings are adjusted to show the new local time
// tzset();
// }
// void initTime(String timezone){
// struct tm timeinfo;
// Serial.println("Setting up time");
// configTime(0, 0, "pool.ntp.org"); // First connect to NTP server, with 0 TZ offset
// if(!getLocalTime(&timeinfo)){
// Serial.println(" Failed to obtain time");
// return;
// }
// Serial.println(" Got the time from NTP");
// // Now we can set the real timezone
// setTimezone(timezone);
// }
// void getNTPTime(){
// struct tm timeinfo;
// if(!getLocalTime(&timeinfo)){
// Serial.println("Failed to obtain time 1");
// return;
// }
// Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S zone %Z %z FROM NTP");
// TMRhrs=timeinfo.tm_hour; // Set time
// TMRmins=timeinfo.tm_min;
// TMRsecs=timeinfo.tm_sec;
// NTPcount=0;
// }
void startWifi(){
WiFi.begin(ssid, wifipw);
Serial.println("Connecting Wifi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.print("Wifi RSSI=");
Serial.println(WiFi.RSSI());
}
// void setTime(int yr, int month, int mday, int hr, int minute, int sec, int isDst){
// struct tm tm;
// tm.tm_year = yr - 1900; // Set date
// tm.tm_mon = month-1;
// tm.tm_mday = mday;
// tm.tm_hour = hr; // Set time
// tm.tm_min = minute;
// tm.tm_sec = sec;
// tm.tm_isdst = isDst; // 1 or 0
// time_t t = mktime(&tm);
// Serial.printf("Setting time: %s", asctime(&tm));
// struct timeval now = { .tv_sec = t };
// settimeofday(&now, NULL);
// TMRhrs=tm.tm_hour; // Set time
// TMRmins=tm.tm_min;
// TMRsecs=tm.tm_sec;
// NTPcount=0;
// }
void LEDsByByte(byte ledToLight) { // Turn all LEDS on or off at once without affecting the global
digitalWrite(latchPin_SIPO, LOW); // ST_CP LOW to keep LEDs from changing while reading serial data
shiftOut(dataPin_SIPO, clockPin_SIPO, MSBFIRST, ledToLight); // Shift out the bits
digitalWrite(latchPin_SIPO, HIGH); // ST_CP HIGH change LEDs
}