Skip to content

16. System Integration

Hero Shot of the Week

Hero

Summary

I have 1 working node with sensors.

And the reception node works too but without much design for it.

Work Process

Calendar

Date To be done What was done
Thursday - 10h local meeting
Friday - FabLab normal work - normal work
Saturday - Bday party for friend
Sunday - some coding
Monday - PCBs
Tuesday - FabLab normal work - normal work
- documentation
Wednesday - 12h Local
- 13h Regional
- 15h Global

Introduction

My work

First I started to put together what I already had. This was true for actual stuff and for virtual stuff.

So I started to put my sensors into my breadboard.

Hero

Did some quick 3D modelling to have a pin for my ESP board.

And more 3D modeling to have name tags (?might not be the best description) so that the onlooker can understand what s.he sees. I had just one issue that I needed to readapt the pin a it what printed in a different direction so it was snapping/failing to quickly. I had no other choice as I wanted to have 2 color prints.

Name Tag

Than I needed to do a new PCB as the one I had only has I2C I/O. I have a thermoresistor that works with analog pin. So I made my first PCB.
Why first ?
Because I fucked up.

  1. Somehow in some places the traces became really thin. So thin that sometimes it just broke.
  2. As I discovered in week 4 the VMA320 needs 3.3V. And I made my PCB with a 5V output...

And for these two reasons my morning was for naught. Of course I already soldered everything when I remembered my error...
Otherwise it would not be fun.

So I remade the PCB in the afternoon with 3.3V output.

PCB

Than for the code part, of course just putting everything together would not work for the first time. So debugging was in order.

Node 2

This code is for the SCD30 sensor (Temperature, CO2, Humidity)

Node 2 Code
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
//
#include <Arduino.h>

// Math library
#include <math.h>

// I2C Communication
#include <Wire.h>

// SCD30 - CO2 Sensor
//#include "SparkFun_SCD30_Arduino_Library.h"
//SCD30 airSensor;
#include <Adafruit_SCD30.h>
Adafruit_SCD30  SCD30;


//BlueTooth MESH
#include "painlessMesh.h"

//JSON file creation & Reading
#include <Arduino_JSON.h>
//#include <ArduinoJson.h>

//RGB LED
#include <FastLED.h>


// ---------- Function declaration ----------

// SCD30 - CO2 Sensor
void CO2S_SCD30_STAR(bool); //function to initialize the CO2 Sensor - SCD30
void CO2S_SCD30(); //CO2 Sensor - SCD30
int SCD30_T;
int SCD30_Humidity;
int SCD30_CO2;

// I2C Scanner -----------
void I2C_Scan(); //I2C Scanner, no Pin required, To check I2C devices connected to the board

//LES SETUP

#define LED_PIN     1 //GPIO //D0 //or D9
#define NUM_LEDS    1
#define BRIGHTNESS  32
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define UPDATES_PER_SECOND 100


CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

int R;
int G;
int B;

void RGB_Send_OFF();
void RGB_Send_ON();

//Button
#define Button_PIN1 43 //GPIO //D6
#define Button_PIN2 7 //GPIO //D8
//#define Button_PIN2 D6 //or D8

// MESH -----------------
//the name of the MESH network
#define   MESH_PREFIX     "whateverYouLike"

//password of the MESH network
#define   MESH_PASSWORD   "somethingSneaky"

// This refers to the the TCP port that you want the mesh server to run on. The default is 5555
#define   MESH_PORT       5555

//Number for this node
int nodeNumber = 2;

//Node ID to send a specific message 
int Node_ID = 1; 

//String to send to other nodes with sensor readings
String final_message;

//It is recommended to avoid using delay() in the mesh network code. 
//To maintain the mesh, some tasks need to be performed in the background. 
//Using delay() will stop these tasks from happening and can cause the mesh to lose stability/fall apart. 
//The following line creates a new Scheduler called userScheduler
Scheduler userScheduler; // to control your personal task

//Create a painlessMesh object called mesh to handle the mesh network
painlessMesh  mesh;

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain

String Message(); // Prototype for sending message

//Create a task called taskSendMessage responsible for calling the sendMessage() function every X (the number) second as long as the program is running.
Task taskSendMessage( TASK_SECOND * 5 , TASK_FOREVER, &sendMessage );


String Message() {
JSONVar jsonReadings;
jsonReadings["node"] = nodeNumber;
jsonReadings["temperature"] = SCD30_T;
jsonReadings["humidity"] = SCD30_Humidity;
jsonReadings["CO2"] = SCD30_CO2;
jsonReadings["TVOC"] = NAN;
// Add more sensor readings as needed
final_message = JSON.stringify(jsonReadings);
return final_message;
}

//The sendMessage() function sends a message to all nodes in the message network (broadcast).
void sendMessage() {

RGB_Send_ON();

String msg = Message();

//board chip ID
//msg += mesh.getNodeId();
//Replaced by nodeNumber

//To broadcast a message, simply use the sendBroadcast() method on the mesh object and pass as argument the message (msg) you want to send.
mesh.sendBroadcast(msg);


//Send to specific Node
//mesh.sendSingle(Node_ID, msg);


//Every time a new message is sent, the code changes the interval between messages (one to five seconds).
//taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));

RGB_Send_OFF();
Serial.println("Message Sent");

}


//several callback functions are created that will be called when specific events happen on the mesh.
//The receivedCallback() function prints the message sender (from) and the content of the message (msg.c_str()).
void receivedCallback( uint32_t from, String &msg ) {
//Serial.printf("Received from %u msg=%s\n", from, msg.c_str());
//The message comes in JSON format, so, we can access the variables as follows:
JSONVar myObject = JSON.parse(msg.c_str());
if (JSON.typeof(myObject) == "undefined") {
Serial.println("Parsing input failed!");
return;
}
int node = myObject["node"];
int temperature_in = myObject["temperature"];
int humidity_in = myObject["humidity"];
int CO2_in = myObject["CO2"];
int TVOC_in = myObject["TVOC"];
//Serial.print(M1_I);
}

//The newConnectionCallback() function runs whenever a new node joins the network. 
//This function simply prints the chip ID of the new node. 
//You can modify the function to do any other task.
void newConnectionCallback(uint32_t nodeId) {
   Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

//The changedConnectionCallback() function runs whenever a connection changes on the network (when a node joins or leaves the network).
void changedConnectionCallback() {
Serial.printf("Changed connections\n");
}

//The nodeTimeAdjustedCallback() function runs when the network adjusts the time, so that all nodes are synchronized. 
//It prints the offset.
void nodeTimeAdjustedCallback(int32_t offset) {
   Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}


// ---------- Setup ----------
void setup() {
// put your setup code here, to run once:
Wire.begin(); // Initialize I2C communication

Serial.begin(115200);   // Initialize Serial Monitor
while (!Serial) { delay(10); } // Wait for serial console to open!

pinMode(LED_BUILTIN, OUTPUT); // Set the built-in LED as output

//LED
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness(  BRIGHTNESS );

currentPalette = RainbowColors_p;
currentBlending = LINEARBLEND;

// Initialize the CO2 Sensor - SCD30
CO2S_SCD30_STAR(true);

//MESH

mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

//Initialize the mesh with the details defined earlier.
mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );
//Assign all the callback functions to their corresponding events.
mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

//Finally, add the taskSendMessage function to the userScheduler. 
//The scheduler is responsible for handling and running the tasks at the right time.
userScheduler.addTask( taskSendMessage );

//Finally, enable the taskSendMessage, so that the program starts sending the messages to the mesh.
taskSendMessage.enable();

//Upload Check
int time = 0;
R = random(0,255);
G = random(0,255);
B = random(0,255);

while (time <= 100){
   for(int i = 0; i < NUM_LEDS; i++ ){
      leds[i].setRGB(R,G,B);  // Set Color HERE!!!
   } 
   FastLED.show();
   FastLED.delay(1000 / UPDATES_PER_SECOND);
   time++;
}
R = 0;
G = 0;
B = 0;
for(int i = 0; i < NUM_LEDS; i++ ){
   leds[i].setRGB(R,G,B);  // Set Color HERE!!!
} 

FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
}


// ---------- Loop ----------
void loop() {
//I2C_Scan(); // Uncomment to scan I2C devices
//RGB_Send_OFF()
digitalWrite(LED_BUILTIN, HIGH); //high turn off the led ...

CO2S_SCD30();

Serial.print("CO2: ");
Serial.println(SCD30_CO2);
Serial.print("T: ");
Serial.println(SCD30_T);
Serial.print("Hum: ");
Serial.println(SCD30_Humidity);
Serial.println("");

mesh.update();
//RGB_Send_ON()


//Serial.println("Hello World");
}


// ---------- Function definitions ----------

// ---------- CO2, T and Humidity Sensor - Sensirion SCD30
void CO2S_SCD30_STAR(bool initialize){
Serial.println("Adafruit SCD30 test!");

// Try to initialize!
if (!SCD30.begin()) {
   Serial.println("Failed to find SCD30 chip");
   while (1) { delay(10); }
}
Serial.println("SCD30 Found!");


// if (!SCD30.setMeasurementInterval(10)){
//   Serial.println("Failed to set measurement interval");
//   while(1){ delay(10);}
// }
Serial.print("Measurement Interval: "); 
Serial.print(SCD30.getMeasurementInterval()); 
Serial.println(" seconds");
}

void CO2S_SCD30(){
if (SCD30.dataReady()){
   Serial.println("Data available!");

   if (!SCD30.read()){ 
      Serial.println("Error reading sensor data");
      SCD30_CO2 =-1;
      SCD30_Humidity=-1;
      SCD30_T=-1;; 
   }

   //Serial.print("Temperature: ");
   //float T = SCD30.temperature;
   SCD30_T = SCD30.temperature;
   //Serial.print(SCD30_T);
   //Serial.println(" degrees C");

   //Serial.print("Relative Humidity: ");
   //float Humidity = SCD30.relative_humidity;
   SCD30_Humidity = SCD30.relative_humidity;
   //Serial.print(SCD30_Humidity);
   //Serial.println(" %");

   //Serial.print("CO2: ");
   //float CO2 = SCD30.CO2;
   SCD30_CO2 = SCD30.CO2;
   //Serial.print(SCD30_CO2);
   //Serial.println(" ppm");
   //Serial.println("");
} 
else {
   //Serial.println("No data");
   //SCD30_CO2 =-1;
   //SCD30_Humidity=-1;
   //SCD30_T=-1;
}
delay(100);
}

// ---------- Integrated LED Blinking
void BlinkLED(int time) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("ON");
delay(time);
digitalWrite(LED_BUILTIN, LOW);
delay(time);
Serial.println("OFF");
}

// ---------- SEND RGB LED Blinking
void RGB_Send_ON(){
int time = 0;
R = random(0,255);
G = random(0,255);
B = random(0,255);

while (time <= 100){
for(int i = 0; i < NUM_LEDS; i++ ){
   leds[i].setRGB(R,G,B);  // Set Color HERE!!!
} 
FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
time++;
}}

void RGB_Send_OFF(){
R = 0;
G = 0;
B = 0;
for(int i = 0; i < NUM_LEDS; i++ ){
leds[i].setRGB(R,G,B);  // Set Color HERE!!!
} 

FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
}

// ---------- Microphone
void Mic(int pin) {
int analogValue = analogRead(pin);
Serial.print("Analog Value: ");
Serial.println(analogValue);
}

// ---------- I2C Scanner
void I2C_Scan() {
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ ) {
   Wire.beginTransmission(address);
   error = Wire.endTransmission();
   if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
      Serial.print("0");
      }
      Serial.println(address,HEX);
      nDevices++;
   }
   else if (error==4) {
      Serial.print("Unknown error at address 0x");
      if (address<16) {
      Serial.print("0");
      }
      Serial.println(address,HEX);
   }    
}
if (nDevices == 0) {
   Serial.println("No I2C devices found\n");
}
else {
   Serial.println("done\n");
}
delay(5000);          
}

I still need to clean up my code and to change from delays to time/task scheduler.

Node 3 code is still in progress.

Node 3

This code is for the SGP30 sensor (CO2, TVOC) and VMA320 sensor (thermoresistor)

Node 3 Code
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
  //
  #include <Arduino.h>

  // Math library
  #include <math.h>

  // I2C Communication
  #include <Wire.h>

  // SGP30 - CO2 Sensor
  #include "Adafruit_SGP30.h"
  Adafruit_SGP30 sgp;

  //BlueTooth MESH
  #include "painlessMesh.h"

  //JSON file creation & Reading
  #include <Arduino_JSON.h>
  //#include <ArduinoJson.h>

  //RGB LED
  #include <FastLED.h>


  // ---------- Function declaration ----------
  // VMA320 - TempSensor
  void TempS_VMA320(int); //Temperature Sensor, Pin required, To measure temperature
  int VMS320_T;
  #define VMA320_PIN A0

  // SGP30 - CO2 Sensor
  void CO2S_SGP30_START(bool); //function to initialize the CO2 Sensor - SGP30
  void CO2S_SGP30(); //CO2 Sensor - SGP30
  int SGP30_TVOC;
  int SGP30_eCO2;
  int counter = 0; // Counter for CO2 Sensor
  uint32_t getAbsoluteHumidity(float, float); // Absolute humidity correction for CO2 Sensor


  // I2C Scanner -----------
  void I2C_Scan(); //I2C Scanner, no Pin required, To check I2C devices connected to the board

  //LES SETUP

  #define LED_PIN     D9 //GPIO //D0 //or D9
  #define NUM_LEDS    1
  #define BRIGHTNESS  32
  #define LED_TYPE    WS2811
  #define COLOR_ORDER GRB
  CRGB leds[NUM_LEDS];

  #define UPDATES_PER_SECOND 100


  CRGBPalette16 currentPalette;
  TBlendType    currentBlending;

  extern CRGBPalette16 myRedWhiteBluePalette;
  extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

  int R;
  int G;
  int B;

  void RGB_Send_OFF();
  void RGB_Send_ON();

  //Button
  #define Button_PIN1 43 //GPIO //D6
  #define Button_PIN2 7 //GPIO //D8
  //#define Button_PIN2 D6 //or D8

  // MESH -----------------
  //the name of the MESH network
  #define   MESH_PREFIX     "whateverYouLike"

  //password of the MESH network
  #define   MESH_PASSWORD   "somethingSneaky"

  // This refers to the the TCP port that you want the mesh server to run on. The default is 5555
  #define   MESH_PORT       5555

  //Number for this node
  int nodeNumber = 3;

  //Node ID to send a specific message 
  int Node_ID = 1; 

  //String to send to other nodes with sensor readings
  String final_message;

  //It is recommended to avoid using delay() in the mesh network code. 
  //To maintain the mesh, some tasks need to be performed in the background. 
  //Using delay() will stop these tasks from happening and can cause the mesh to lose stability/fall apart. 
  //The following line creates a new Scheduler called userScheduler
  Scheduler userScheduler; // to control your personal task

  //Create a painlessMesh object called mesh to handle the mesh network
  painlessMesh  mesh;

  // User stub
  void sendMessage() ; // Prototype so PlatformIO doesn't complain

  String Message(); // Prototype for sending message

  //Create a task called taskSendMessage responsible for calling the sendMessage() function every X (the number) second as long as the program is running.
  Task taskSendMessage( TASK_SECOND * 5 , TASK_FOREVER, &sendMessage );


  String Message() {
  JSONVar jsonReadings;
  jsonReadings["node"] = nodeNumber;
  jsonReadings["temperature"] = VMS320_T;
  jsonReadings["humidity"] = NAN;
  jsonReadings["CO2"] = SGP30_eCO2;
  jsonReadings["TVOC"] = SGP30_TVOC;
  // Add more sensor readings as needed
  final_message = JSON.stringify(jsonReadings);
  return final_message;
  }

  //The sendMessage() function sends a message to all nodes in the message network (broadcast).
  void sendMessage() {

  RGB_Send_ON();

  String msg = Message();

  //board chip ID
  //msg += mesh.getNodeId();
  //Replaced by nodeNumber

  //To broadcast a message, simply use the sendBroadcast() method on the mesh object and pass as argument the message (msg) you want to send.
  mesh.sendBroadcast(msg);


  //Send to specific Node
  //mesh.sendSingle(Node_ID, msg);


  //Every time a new message is sent, the code changes the interval between messages (one to five seconds).
  //taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));

  RGB_Send_OFF();
  Serial.println("Message Sent");

  }


  //several callback functions are created that will be called when specific events happen on the mesh.
  //The receivedCallback() function prints the message sender (from) and the content of the message (msg.c_str()).
  void receivedCallback( uint32_t from, String &msg ) {
  //Serial.printf("Received from %u msg=%s\n", from, msg.c_str());
  //The message comes in JSON format, so, we can access the variables as follows:
  JSONVar myObject = JSON.parse(msg.c_str());
  if (JSON.typeof(myObject) == "undefined") {
  Serial.println("Parsing input failed!");
  return;
  }
  int node = myObject["node"];
  int temperature_in = myObject["temperature"];
  int humidity_in = myObject["humidity"];
  int CO2_in = myObject["CO2"];
  int TVOC_in = myObject["TVOC"];
  //Serial.print(M1_I);
  }

  //The newConnectionCallback() function runs whenever a new node joins the network. 
  //This function simply prints the chip ID of the new node. 
  //You can modify the function to do any other task.
  void newConnectionCallback(uint32_t nodeId) {
     Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
  }

  //The changedConnectionCallback() function runs whenever a connection changes on the network (when a node joins or leaves the network).
  void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
  }

  //The nodeTimeAdjustedCallback() function runs when the network adjusts the time, so that all nodes are synchronized. 
  //It prints the offset.
  void nodeTimeAdjustedCallback(int32_t offset) {
     Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
  }


  // ---------- Setup ----------
  void setup() {
  // put your setup code here, to run once:
  Wire.begin(); // Initialize I2C communication

  Serial.begin(115200);   // Initialize Serial Monitor
  while (!Serial) { delay(10); } // Wait for serial console to open!

  pinMode(LED_BUILTIN, OUTPUT); // Set the built-in LED as output

  //LED
  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness(  BRIGHTNESS );

  currentPalette = RainbowColors_p;
  currentBlending = LINEARBLEND;

  pinMode(VMA320_PIN, INPUT);   // Set the pin input for VMA320 Thermistor / Temp Sensor

  // Initialize the CO2 Sensor - SGP30
  CO2S_SGP30_START(true);

  //MESH

  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages
  //mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

  //Initialize the mesh with the details defined earlier.
  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );
  //Assign all the callback functions to their corresponding events.
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

  //Finally, add the taskSendMessage function to the userScheduler. 
  //The scheduler is responsible for handling and running the tasks at the right time.
  userScheduler.addTask( taskSendMessage );

  //Finally, enable the taskSendMessage, so that the program starts sending the messages to the mesh.
  taskSendMessage.enable();

  //Upload Check
  int time = 0;
  R = random(0,255);
  G = random(0,255);
  B = random(0,255);

  while (time <= 100){
     for(int i = 0; i < NUM_LEDS; i++ ){
        leds[i].setRGB(R,G,B);  // Set Color HERE!!!
     } 
     FastLED.show();
     FastLED.delay(1000 / UPDATES_PER_SECOND);
     time++;
  }
  R = 0;
  G = 0;
  B = 0;
  for(int i = 0; i < NUM_LEDS; i++ ){
     leds[i].setRGB(R,G,B);  // Set Color HERE!!!
  } 

  FastLED.show();
  FastLED.delay(1000 / UPDATES_PER_SECOND);
  }


  // ---------- Loop ----------
  void loop() {
  //I2C_Scan(); // Uncomment to scan I2C devices
  //RGB_Send_OFF()
  digitalWrite(LED_BUILTIN, HIGH); //high turn off the led ...

  TempS_VMA320(VMA320_PIN);

  CO2S_SGP30();

  mesh.update();
  //RGB_Send_ON()


  }


  // ---------- Function definitions ----------
  // ---------- CO2 Sensor - Sensirion SGP30 eCO2 & TVOC Sensor

  void CO2S_SGP30_START(bool initialize){
     if (!initialize) return;  // If false, exit function

     // Initialize I2C communication for the SGP30
     Serial.println("SGP30 test");

     if (! sgp.begin()){
        Serial.println("Sensor not found :(");
        while (1);
     }
     Serial.print("Found SGP30 serial #");
     Serial.print(sgp.serialnumber[0], HEX);
     Serial.print(sgp.serialnumber[1], HEX);
     Serial.println(sgp.serialnumber[2], HEX);
     // If you have a baseline measurement from before you can assign it to start, to 'self-calibrate'
     //sgp.setIAQBaseline(0x8E68, 0x8F41);  // Will vary for each sensor!
  }

  /* return absolute humidity [mg/m^3] with approximation formula
  * @param temperature [°C]
  * @param humidity [%RH]
  */


  uint32_t getAbsoluteHumidity(float temperature, float humidity) {
     // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
     const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
     const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
     return absoluteHumidityScaled;
  }


  void CO2S_SGP30(){
     // If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humidity compensation for the air quality signals
     //float temperature = 22.1; // [°C]
     //float humidity = 45.2; // [%RH]
     //sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));


     if (! sgp.IAQmeasure()) {
        Serial.println("Measurement failed");
        //return;
     }


     Serial.print("TVOC "); 
     float TVOC = sgp.TVOC;
     Serial.print(TVOC); 
     Serial.print(" ppb\t");

     Serial.print("eCO2 "); 
     float eCO2 = sgp.eCO2;
     Serial.print(eCO2); 
     Serial.println(" ppm");

     /*
     if (! sgp.IAQmeasureRaw()) {
        Serial.println("Raw Measurement failed");
        //return;
     }
     Serial.print("Raw H2 "); 
     Serial.print(sgp.rawH2); 
     Serial.print(" \t");

     Serial.print("Raw Ethanol "); 
     Serial.print(sgp.rawEthanol); 
     Serial.println("");
     */
     delay(1000);


     /*
     counter++;
     if (counter == 30) {
        counter = 0;

        uint16_t TVOC_base, eCO2_base;
        if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
        Serial.println("Failed to get baseline readings");
        return;
        }
        Serial.print("****Baseline values: eCO2: 0x"); 
        Serial.print(eCO2_base, HEX);

        Serial.print(" & TVOC: 0x"); 
        Serial.println(TVOC_base, HEX);
     }
     */

     SGP30_eCO2 = eCO2;
     SGP30_TVOC = TVOC;
     //Code modified from Adafruit SGP30 example
  }



  // ---------- Temperature Sensor - VMA 320
  void TempS_VMA320(int pin){
     float reading;

     // The beta coefficient of the thermistor (usually 3000-4000)
     #define BCOEFFICIENT 3950
     // the value of the 'other' resistor
     #define SERIESRESISTOR 10000     
     // resistance at 25 degrees C
     #define THERMISTORNOMINAL 10000      
     // temp. for nominal resistance (almost always 25 C)
     #define TEMPERATURENOMINAL 25 

     reading  = analogRead(pin);

     reading = 4095 / reading - 1;
     reading = SERIESRESISTOR / reading;
     //Serial.print("Thermistor resistance "); 
     //Serial.println(reading);

     float steinhart;
     steinhart = reading / THERMISTORNOMINAL;     // (R/Ro)
     steinhart = log(steinhart);                  // ln(R/Ro)
     steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
     steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
     steinhart = 1.0 / steinhart;                 // Invert
     steinhart -= 273.15;                         // convert absolute temp to C


     //Serial.print("Temperature "); 
     //Serial.print(steinhart);
     //Serial.println(" *C");


     VMS320_T = steinhart;

     //Modified from: https://learn.adafruit.com/thermistor/using-a-thermistor
  }




  // ---------- Integrated LED Blinking
  void BlinkLED(int time) {
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.println("ON");
  delay(time);
  digitalWrite(LED_BUILTIN, LOW);
  delay(time);
  Serial.println("OFF");
  }

  // ---------- SEND RGB LED Blinking
  void RGB_Send_ON(){
  int time = 0;
  R = random(0,255);
  G = random(0,255);
  B = random(0,255);

  while (time <= 100){
  for(int i = 0; i < NUM_LEDS; i++ ){
     leds[i].setRGB(R,G,B);  // Set Color HERE!!!
  } 
  FastLED.show();
  FastLED.delay(1000 / UPDATES_PER_SECOND);
  time++;
  }}

  void RGB_Send_OFF(){
  R = 0;
  G = 0;
  B = 0;
  for(int i = 0; i < NUM_LEDS; i++ ){
  leds[i].setRGB(R,G,B);  // Set Color HERE!!!
  } 

  FastLED.show();
  FastLED.delay(1000 / UPDATES_PER_SECOND);
  }


  // ---------- I2C Scanner
  void I2C_Scan() {
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
     Wire.beginTransmission(address);
     error = Wire.endTransmission();
     if (error == 0) {
        Serial.print("I2C device found at address 0x");
        if (address<16) {
        Serial.print("0");
        }
        Serial.println(address,HEX);
        nDevices++;
     }
     else if (error==4) {
        Serial.print("Unknown error at address 0x");
        if (address<16) {
        Serial.print("0");
        }
        Serial.println(address,HEX);
     }    
  }
  if (nDevices == 0) {
     Serial.println("No I2C devices found\n");
  }
  else {
     Serial.println("done\n");
  }
  delay(5000);          
  }

Node 3 code is not anymore in progress.

I also found some copper cables that I would like to use for the connection. But now I need female and male end to create my cables. Or come up with some other idea.

Copper

I also needed to cut some more bread boards.

New Idea

Idea 1

Source

Idea 2 Idea 2

Source

Idea 3

Source

Lets see if I can do something like this with the SDC30.


Learning Outcome

I am getting tired.

I need a real brake.



Assignment Check

  • Design and document the system integration for your final project