Sensor display on a TFT Touchscreen
By kaydub
Here’s a demo of data from the SensorPacks being displayed on a TFT Touchscreen/shield I picked up from Adafruit. Writing a simple UI via graphics primitives reminded me of building UI’s back in the day, where all you have are lines, circles, and x/y coordinates to play with. There wasn’t a lot of data space left over to build functionality, but I managed to get a quick-and-dirty analog clock, as well as the ability to store data for 4 individual SensorPacks. The XBee listens for data, and when it recognizes a packet from a SensorPack, it either updates the entry, or adds it to the list.
I ended up with about 200 bytes of storage left, after porting and streamlining my sensor reading code from the other displays I built, so adding more functionality will require a bit of code rework, but I’m pretty happy with this so far. Will likely add gauges, and the ability to show history at some point.
#include <NewSoftSerial.h> #include "TFTLCD.h" #include "TouchScreen.h"boolean firstRun = true;
//#define DEBUG 2 //#define DEBUG 0
#if not defined USE_ADAFRUIT_SHIELD_PINOUT #error "For use with the shield, make sure to #define USE_ADAFRUIT_SHIELD_PINOUT in the TFTLCD.h library file" #endif
// These are the pins for the shield! #define YP A1 // must be an analog pin, use "An" notation! #define XM A2 // must be an analog pin, use "An" notation! #define YM 7 // can be a digital pin #define XP 6 // can be a digital pin
#define TS_MINX 150 #define TS_MINY 120 #define TS_MAXX 920 #define TS_MAXY 940
// For better pressure precision, we need to know the resistance // between X+ and X- Use any multimeter to read it // For the one we’re using, its 300 ohms across the X plate TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
// The control pins can connect to any pins but we’ll use the // analog lines since that means we can double up the pins // with the touch screen (see the TFT paint example) #define LCD_CS A3 // Chip Select goes to Analog 3 #define LCD_CD A2 // Command/Data goes to Analog 2 #define LCD_WR A1 // LCD Write goes to Analog 1 #define LCD_RD A0 // LCD Read goes to Analog 0
// you can also just connect RESET to the arduino RESET pin #define LCD_RESET A4
/* For the 8 data pins: Duemilanove/Diecimila/UNO/etc (‘168 and ‘328 chips) microcontoller: D0 connects to digital 8 D1 connects to digital 9 D2 connects to digital 2 D3 connects to digital 3 D4 connects to digital 4 D5 connects to digital 5 D6 connects to digital 6 D7 connects to digital 7
For Mega’s use pins 22 thru 29 (on the double header at the end) */
// Color definitions #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF
TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
#define MINPRESSURE 10 #define MAXPRESSURE 1000
#define BOXSIZE 40 #define PENRADIUS 4
int tftRotation = 1;
#define MENU 1 #define DETAIL 2 #define CLOCK 3 #define DETAILGRAPH 4
unsigned int displayMode = MENU; unsigned int detailID = 0;
NewSoftSerial xbSerial(2,3);
// a id t T h p c dd rt reset
#define COMMANDS "aidtTt0t1t2t3hpcddrtreset" // commands we know about, mushed together
#define MAXTOKEN 32 // Maximum number of parsable tokens per packet #define MAXTOKENLEN 32 // No one token’s command or data should exceed this #define MAXSTRING 80 // SoftSerial buffer is 64 bytes long, so we can’t get more than that at once. // This leaves a little buffer in case we get a couple packets in a row.
#define INVALID -99
void sClear(char *theString, int len=MAXSTRING); // Clears a string, optionally a different length than MAXSTRING
//void tftPrint(char *text, uint16_t color=GREEN);// Define sensor IDs and their relative index positions #define SENSORONE 0 #define SENSORTWO 1 #define MAXSENSORS 4 uint8_t nsid = SENSORONE; // Which sensor do we want to display data for? char *sid = {"VoltBarn Default SensorID"}; // Until we get packets with sensor ID’s, use a default
// Globals uint16_t mpt[MAXSENSORS] = {INVALID,INVALID,INVALID,INVALID}; // Temperature, per sensor uint16_t mph[MAXSENSORS] = {INVALID,INVALID,INVALID,INVALID}; // Humidity, per sensor uint16_t mpp[MAXSENSORS] = {INVALID,INVALID,INVALID,INVALID}; // Pressure, per sensor uint16_t mpu[MAXSENSORS] = {INVALID,INVALID,INVALID,INVALID}; // Time of last update per sensor uint16_t mpc[MAXSENSORS] = {CYAN, GREEN, YELLOW, MAGENTA}; char *mpi[MAXSENSORS] = {"VoltBarnSensorID1", "VoltBarnSensorID2", "VoltBarnSensorID3", "VoltBarnSensorID4"}; float mpat[MAXSENSORS][4] = { {-99, -99, -99, -99}, {-99, -99, -99, -99}, {-99, -99, -99, -99}, // {-99, -99, -99, -99}, {-99, -99, -99, -99} }; // Auxillary temp sensors per SensorPack
uint16_t rx1[MAXSENSORS], rx2[MAXSENSORS], ry1[MAXSENSORS], ry2[MAXSENSORS];
uint8_t maxID = 0;
short int tempSid = 0; uint16_t ctime = 1200; // current time uint16_t pt = 500, ph = 500, pp = 2950; // last temp, humidity, pressure received float ft = INVALID, fh = INVALID, fp = INVALID; // Set to "no data yet" values (> 9999) for temp, humidty, pressure
char thePacket[MAXSTRING]; // Primary info, the packet received char tempString[MAXSTRING]; // used in subString char t[MAXSTRING]; // used in sTrim
uint16_t idx, idx1; // Loop variable for routines that don’t call others
long int lastUpdate;
uint8_t * heapptr, * stackptr; void check_mem() { stackptr = (uint8_t *)malloc(4); // use stackptr temporarily heapptr = stackptr; // save value of heap pointer free(stackptr); // free up the memory again (sets stackptr to 0) stackptr = (uint8_t *)(SP); // save value of stack pointer if (heapptr > stackptr) { Serial.print("ERROR**************************************************heap: "); Serial.print((int)heapptr); Serial.print(" > stackptr: "); Serial.println((int)stackptr); } #ifdef DEBUG >= 3 Serial.print("**************************************************heap: "); Serial.print((int)heapptr); Serial.print(" < stackptr: "); Serial.println((int)stackptr); #endif }
void setup(void) { char incomingByte;
xbSerial.begin(9600); // XBee
//Serial.begin(9600); Serial.begin(115200);
tft.reset();
uint16_t identifier = tft.readRegister(0x0); if (identifier == 0x9325) { Serial.println("Found ILI9325"); } else if (identifier == 0x9328) { Serial.println("Found ILI9328"); } else { Serial.print("Unknown driver chip "); Serial.println(identifier, HEX); while (1); }
tft.initDisplay();
//tft.setRotation(tftRotation); tft.fillScreen(BLACK); tft.setCursor(0, 0); tft.setRotation(tftRotation); tft.setTextColor(RED); tft.setTextSize(2); tft.println("VoltBarn SensorPack");
delay(1500); xbSerial.print("+++"); delay(1500); if (xbSerial.available() == 0) xbSerial.print("+++"); delay(1000); while (xbSerial.available()) { // Clear out the "OK" incomingByte = xbSerial.read(); } /* tft.println("XBee info:"); tftXbee("ATMY"); tftXbee("ATID"); tftXbee("ATDL"); delay(1000); */ xbSerial.print("ATCN\r");
lastUpdate = millis(); check_mem(); }
/* void tftXbee(String command) { char incomingByte; int b;
xbSerial.print(command); xbSerial.print(’\r’); tft.print(command); tft.print(":"); delay(1000); while (xbSerial.available() > 0) { incomingByte = xbSerial.read(); tft.print(incomingByte); } tft.println(""); delay(1000); } */
// *********************************** // ************** loop // ***********************************
void loop() {
char incomingByte; char cmd[MAXTOKENLEN], data[MAXTOKENLEN]; byte ntok = 0; //char displayItem; boolean tokenFound; uint16_t i; char xtime[6]; uint16_t tftWidth, tftHeight; boolean touched = false; uint8_t bytesA = 0, bytesR = 0;
#ifdef DEBUG >= 2 // Sample data if (firstRun) { //sCopy(thePacket,":id:test1-01:t:32.0:p:26.02:h:27.0:"); //splitTokens(); sCopy(thePacket,":id:foo1-01:t:32.0:p:26.02:h:27.0:"); splitTokens(); sCopy(thePacket,":id:bar1-01:t:32.0:p:26.02:h:27.0:c:0250:"); splitTokens(); firstRun = false; } #endif
tftWidth = tft.width(); tftHeight = tft.height();
// First thing, check for a touch
tft.setRotation(0); // make sure we’re at the default rotation to read the input digitalWrite(13, HIGH); Point p = ts.getPoint(); digitalWrite(13, LOW);
pinMode(XM, OUTPUT); pinMode(YP, OUTPUT);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
// turn from 0->1023 to tft.width p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0); // x, y input are absolute, regardless of rotation // x, y output changes, depending on rotation Serial.print("[");Serial.print(tftWidth);Serial.print(",");Serial.print(tftHeight);Serial.print("] "); Serial.print("X = "); Serial.print(p.x); Serial.print("\tY = "); Serial.print(p.y); Serial.print("\tPressure = "); Serial.println(p.z); if (displayMode == CLOCK || displayMode == DETAIL) { displayMenu(); displayMode = MENU; } else { for (i = 0; i < maxID; i++) { if (p.x > rx1[i] && p.x < rx2[i] && p.y > ry1[i] && p.y < ry2[i]) { //Serial.println("In bounding box"); if (displayMode == MENU) { tft.fillRect(rx1[i], ry1[i], BOXSIZE, (BOXSIZE*8)-10, mpc[i]); detailID = i; displayDetail(detailID); displayMode = DETAIL; touched = true; } else { displayMenu(); displayMode = MENU; touched = false; } // else } // if } // for if (touched == false && p.x > tftWidth-40) { Serial.println("Touched the clock"); displayClockAnalog(); displayMode = CLOCK; touched = true; } // if } // else
if (p.y < (TS_MINY-5)) { Serial.println("erase"); // press the bottom of the screen to erase //tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK);
} }// Now, we grab packets and process them. sClear(thePacket); // Null out the packet when the loop starts tokenFound = false; while (bytesA = xbSerial.available()) { bytesR++; #if DEBUG >= 1 Serial.print((int)bytesA); Serial.print(" Byte(s) available ("); Serial.print((int)bytesR); Serial.println("):"); #endif if (bytesR > MAXSTRING) { // Too much data coming in at once, bail and process what we’ve got thePacket[MAXSTRING-2] = ‘:’; thePacket[MAXSTRING-1] = ‘\0’; break; } // read the incoming byte: incomingByte = xbSerial.read(); // Ignore any cruft we get until we get our first token separator. ACK errors cause havok // and resetting if ((incomingByte == ‘:’) || (tokenFound)) { tokenFound = true; sAppend(thePacket,incomingByte); #if DEBUG >= 1 Serial.print("I received: "); Serial.print(incomingByte); Serial.print("["); Serial.print(incomingByte,HEX); Serial.println("]"); #endif if (incomingByte == 0xD) // Started getting a corrupted packet with a 0xD in the middle, bail break; } else { Serial.print("#"); } } if (sLength(thePacket) > 0) { check_mem(); lastUpdate = millis(); Serial.println(thePacket); splitTokens(); // break into an array of tokenized strings
switch (displayMode) { case MENU: displayMenu(); break; case CLOCK: displayClockAnalog(); break; case DETAIL: displayDetail(detailID); break; } } }// *********************************** // ************** displayDetail // *********************************** void displayDetail (uint16_t i) { tft.fillScreen(BLACK); tft.setCursor(0, 0); tft.setRotation(tftRotation); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("ID:"); tft.println(mpi[i]); tft.print("Temp:"); tft.print(mpt[i]/((mpt[i] > 999) ? 100: 10)); tft.print("."); tft.print(mpt[i]%((mpt[i] > 999) ? 100: 10)); tft.println("F"); for (idx = 0; idx < 4; idx++) { if (mpat[i][idx] != -99) { tft.print("Temp"); tft.print(idx); tft.print(":"); tft.print(mpat[i][idx]); tft.println("F"); } } tft.print("Pressure:"); tft.print(mpp[i]/((mpp[i] > 999) ? 100: 10)); tft.print("."); tft.print(mpp[i]%((mpp[i] > 999) ? 100: 10)); tft.println("Hg"); tft.print("Humidity:"); tft.print(mph[i]/((mph[i] > 999) ? 100: 10)); tft.print("."); tft.print(mph[i]%((mph[i] > 999) ? 100: 10)); tft.println("%"); tft.print("Last update:"); displayTime(mpu[i], 3); tft.print("Time: "); displayTime(ctime, 3); }
// *********************************** // ************** displayMenu // *********************************** void displayMenu () { char xtime[6];
// Print tft info: tft.fillScreen(BLACK); tft.setCursor(0, 0); tft.setRotation(tftRotation); tft.setTextSize(4); tft.setTextColor(RED); tft.print("Time: "); displayTime(ctime, 4); tft.setRotation(0);
// 0,0 is bottom left and 240, 0 is upper right in this orientation 180,120,60 for (idx = 0;idx < maxID; idx++) { for (uint8_t ii = 0; ii < 8; ii++) { tft.drawRect(((BOXSIZE*(4-idx))-(ii/2)), (ii/2), BOXSIZE, (BOXSIZE8)-10, WHITE); } rx1[idx] = (BOXSIZE(4-idx)); ry1[idx] = 0; rx2[idx] = rx1[idx] + BOXSIZE; ry2[idx] = BOXSIZE * 8;
}tft.setRotation(tftRotation); for (idx = 0; idx < maxID; idx++) { tft.setTextColor(mpc[idx]); tft.setTextSize(2); tft.print("\n "); // left hand padding
tft.setTextSize(3); tft.print(mpi[idx]); Serial.println(mpi[idx]); Serial.print(" Temp: "); Serial.println(mpt[idx]); tft.print(":"); tft.print(mpt[idx]/((mpt[idx] > 999) ? 100: 10)); tft.print("."); tft.print(mpt[idx]%((mpt[idx] > 999) ? 100: 10)); tft.println("F"); }
}// *********************************** // ************** displayClock // *********************************** /* void displayClock () { tft.fillScreen(BLACK); tft.setCursor(0, 0); tft.setRotation(tftRotation); tft.setTextSize(10); tft.println(""); displayTime(ctime,11); tft.setTextSize(2); tft.setRotation(0); } */
// *********************************** // ************** displayTime // *********************************** void displayTime (uint16_t time,uint8_t tsize) { uint16_t ttime; char xtime[6]; short int idx; // Override the global with one that can go negative
#ifdef DEBUG >= 3 Serial.print("In displayTime with: "); Serial.println(time); #endif
if (millis() > lastUpdate + 120000) tft.setTextColor(YELLOW); else tft.setTextColor(RED); tft.setTextSize(tsize);
// Make sure we print a 4 digit time for (idx = 4, ttime=time; idx >= 0; idx–) { if (idx == 2) xtime[idx] = ‘:’; else { xtime[idx] = 48 + (ttime % 10);
ttime /= 10; } } xtime[5] = ‘\0’; tft.println(xtime); Serial.println("Exiting displayTime"); }// *********************************** // ************** displayClockAnalog // *********************************** void displayClockAnalog () {
// Set rotation, so everything is drawn in perspective tft.setRotation(tftRotation);
uint16_t x2, y2; short int i;
#define HOUR (ctime / 100) % 12 #define MINUTE (ctime % 100) % 60 #define MIDPX tft.width()/2 #define MIDPY tft.height()/2
Serial.print("Displaying hour: "); Serial.print(HOUR); Serial.print(" minute: "); Serial.println(MINUTE);
// Rotate hands 90 degrees, 0,0 bottom left //tft.setRotation(0); //hour = (hour + 3) % 12; //minute = (minute + 15) % 60;
// Or, reset rotation // tft.setRotation(tftRotation);
tft.fillScreen(BLACK); tft.setCursor(0, 0); for (idx = 0; idx < 5; idx++) { tft.drawCircle(MIDPX, MIDPY, (tft.height() < tft.width()) ? MIDPY - idx: MIDPX - idx, RED); }
// Draw hour hand, compensating for how many minutes past the hour, so the hand doesn't just "jump" every hour for (i = -2; i < 3; i++) { x2 = MIDPX - 75 * sin((3.141596 / 180.0 * -((HOUR + (MINUTE/60.0)) * 30.0))); y2 = MIDPY - 75 * cos((3.141596 / 180.0 * -((HOUR + (MINUTE/60.0)) * 30.0))); tft.drawLine(MIDPX+i, MIDPY+i, x2+i, y2+i, BLUE); }
for (i = -2; i < 3; i++) {
x2 = MIDPX - 100 * sin((3.141596 / 180 * -(MINUTE * 6))); y2 = MIDPY - 100 * cos((3.141596 / 180 * -(MINUTE * 6))); tft.drawLine(MIDPX+i, MIDPY+i, x2+i, y2+i, GREEN); } }// *********************************** // ************** parseToken // ***********************************
void parseToken(char *tok, char *val, int wackaSid) { Serial.print("Parsing for token: "); Serial.print(tok); Serial.print(" with value: "); Serial.println(val);
if (sEquals(tok,"c")) { // clock time ctime = atoi(val); Serial.print("Time: "); Serial.println(ctime); } if ((sEquals(tok,"a")) || (sEquals(tok,"id"))) { // sensor id sid = val; tempSid = pickSensor(sid); if (tempSid < 0) return; } Serial.print("Parse token, sid is "); Serial.println(tempSid); mpu[tempSid] = ctime; // Set the last-updated time for this sensor to now if (sEquals(tok,"t")) { // temperature ft = atof(val); // set temp to null terminated string mpt[tempSid] = int(ft * 10); pt = mpt[tempSid]; } else if (sEquals(tok,"T")) { // alternate temperature //ft = atof(val); } else if (sEquals(tok,"h")) { // humidity fh = atof(val); mph[tempSid] = int(fh * 10); ph = mph[tempSid]; } else if (sEquals(tok,"p")) { // pressure fp = atof(val); mpp[tempSid] = int(fp * 100); pp = mpp[tempSid]; } else if (sEquals(tok,"reset")) { if (sEquals(val,"reset")) { //resetDefaults(); // we got a "reset/reset" token, undo any customizations } } else if (sEquals(tok, "t0")) { mpat[tempSid][0] = atof(val); } else if (sEquals(tok, "t1")) { mpat[tempSid][1] = atof(val); } else if (sEquals(tok, "t2")) { mpat[tempSid][2] = atof(val); } else if (sEquals(tok, "t3")) { mpat[tempSid][3] = atof(val); } }
// *********************************** // ************** splitTokens // *********************************** int splitTokens() { char tmpString[MAXSTRING]; int ntok = 0; char *token = ":"; //char **outString = theTokens; //char *theString = thePacket; char cmd[MAXTOKENLEN], data[MAXTOKENLEN]; boolean getCommand = true; int mySid = 0;
#ifdef DEBUG Serial.println("Entering splitTokens…"); Serial.println(thePacket);
if (sContains(thePacket, token)) Serial.println("Got a token"); else Serial.println("no tokens"); #endif
while (sContains(thePacket, token)) { #ifdef DEBUG Serial.println("Getting token"); #endif check_mem(); if (sIndexOf(thePacket, token) > 0) { if (getCommand) { sClear(cmd); sCopy(cmd, sSubstring(thePacket, 0, sIndexOf(thePacket, token))); sTrim(cmd); if (sContains(COMMANDS, cmd)) // Make sure this is a command getCommand = false; } else { sClear(data); sCopy(data, sSubstring(thePacket, 0, sIndexOf(thePacket, token))); sTrim(data); getCommand = true; parseToken(cmd, data, tempSid); } ntok++; } sClear(tmpString); sCopy(tmpString,sSubstring(thePacket, sIndexOf(thePacket, token) + 1, sLength(thePacket)));
sClear(thePacket); sCopy(thePacket, tmpString);
// This indicates a corrupt string, indicating we’ve run out of memory somewhere if (sLength(thePacket) > MAXSTRING) { Serial.println(""); Serial.print(sLength(thePacket)); Serial.println("******** CORRUPT STRING ERROR *********"); sClear(thePacket); } } // Check to see if we’re at the end of the string, and if so // make sure and grab the last token if (sLength(thePacket) > 0) { ntok++; } Serial.println("Exiting"); sClear(thePacket); return(ntok); }
// *********************************** // ************** Supporting string functions // ***********************************
// *********************************** // ************** sSubstring // *********************************** char *sSubstring(char *theString, int s, int e) { int ii = 0;
#ifdef DEBUG >= 3 Serial.print("entering sSubstring"); check_mem(); #endif
sClear(tempString);
for (int i = s,ii = 0; i < e; i++, ii++) { tempString[ii] = theString[i]; }
#ifdef DEBUG >= 3 Serial.print("leaving sSubstring"); check_mem(); #endif return(tempString); }
// *********************************** // ************** sAppend // *********************************** void sAppend(char theString[], char token) { theString[sLength(theString)] = token;
}
// *********************************** // ************** sCopy // *********************************** void sCopy(char *theString, char *newString) {
for (idx = 0; idx < sLength(newString); idx++) theString[idx] = newString[idx]; theString[sLength(newString)] = ‘\0’; #ifdef DEBUG >= 3 Serial.print("In sCopy "); check_mem(); Serial.print("Copied: ""); Serial.print(newString); Serial.print("" To: ""); Serial.print(theString); Serial.println("""); #endif }
// *********************************** // ************** sIndexOf // *********************************** int sIndexOf(char *theString, char *token) { for (idx = 0; idx < MAXSTRING; idx++) { if (theString[idx] == token[0]) return(idx); } return (-1); }
// *********************************** // ************** sContains // *********************************** boolean sContains(char *theString, char *token) { uint8_t ii = 0; if (sLength(theString) == 0) return false; for (idx = 0; idx < sLength(theString); idx++) { if (theString[idx] == token[ii]) { for (ii = 1; ii < sLength(token); ii++, idx++) { if (theString[idx] != token[ii]) break; } return(true); } } return(false); }
// *********************************** // ************** sLength // *********************************** byte sLength(char theString[]) { for (idx1 = 0; idx1 < MAXSTRING; idx1++) { if (theString[idx1] == ‘\0’) { return(idx1); } } return (-1); }
// *********************************** // ************** sClear // *********************************** void sClear(char *theString, int len) { for (idx = 0; idx < len; idx++) theString[idx] = ‘\0’; }
// *********************************** // ************** sEquals // *********************************** boolean sEquals (char *theString, char *token) { if (sLength(theString) != sLength(token)) return(false); for (idx = 0; idx < sLength(theString); idx++) { if (theString[idx] != token[idx]) { return(false); } } return(true); }
// *********************************** // ************** sTrim // *********************************** void sTrim(char *theString) {
boolean s = false; uint8_t ix = 0, ii; uint8_t b;
sClear(t); ii = sLength(theString); #ifdef DEBUG >= 2 Serial.print("In sTrim"); check_mem(); /* Serial.print("in: i - "); Serial.print((int)ix); Serial.print(" ii - "); Serial.println((int)ii); */ #endif while ((ix < ii) && (theString[ix] == ’ ‘)) ix++;
//Serial.print("{"); b = theString[ii]; //Serial.print(b,HEX); //Serial.println("}");
while ((ii > 0) && ((theString[ii] == 0x20) || (theString[ii] == 0x00))) { theString[ii] = 0x00; ii–; } #if DEBUG >=3 Serial.print("trim "); Serial.print((int)ix); Serial.print(" to "); Serial.print((int)ii); Serial.print(" with ‘"); Serial.print(theString); Serial.print("’ to ‘"); #endif sCopy(t, sSubstring(theString,ix,sLength(theString))); #ifdef DEBUG >= 3 Serial.print("Trimmed to ‘"); Serial.print(t); Serial.println("’"); check_mem(); #endif sClear(theString); sCopy(theString, t); }
// *********************************** // ************** Other support functions // ***********************************
// *********************************** // ************** pickSensor // ***********************************
short int pickSensor(char *sid) {
/* Update this to return a sensor ID if there is a map to any we’ve ever seen, or create a new ID if it’s not found. Need to change the fixed strings to an array that gets filled as sensors check in, and then use the array index as the ID */
for (uint8_t idx = 0; idx < maxID; idx++) { // Override the idx global if (sContains(sid,mpi[idx])) { #ifdef DEBUG >= 0 Serial.print("I know this sensor ‘"); Serial.print(sid); Serial.print("’ is id: "); Serial.println(idx); #endif return idx; } } if (maxID < MAXSENSORS) { sCopy(mpi[maxID],sid); maxID++; #ifdef DEBUG > 0 Serial.print("I’ve never seen this sensor ‘"); Serial.print(sid); Serial.print("’ is id: "); Serial.println(maxID-1); #endif return maxID-1; } else { return -1; } }