2
$\begingroup$

This post is a continuation and modified version of an earlier post from few years ago.

Please help with the Dynamic function capturing data from a Serial stream from Arduino. I am not having luck with Dynamic capture of data from an Arduino serial port. Here is my code

dev = DeviceOpen["Serial", "COM3"]

parseData[{val1__, 44, val2__, 44, val3__}] := 
 ToExpression@FromCharacterCode@# & /@ {{val1}, {val2}, {val3}}
parseData[___] := Sequence[]

rawReadings = {}

task = SessionSubmit[
  ScheduledTask[
   AppendTo[rawReadings, 
    DeviceReadBuffer[dev, "ReadTerminator" -> 10]], {1, 100}, 
   "AutoRemove" -> true]]

rawReadings

test1 = parseData /@ rawReadings

ListLinePlot[Transpose[parseData /@ rawReadings], 
  PlotLegends -> Automatic] // Dynamic

DeviceClose[dev]

The Arduino sketch sends a group of 3 integers separated by a coma (ASCii 44) . Sometimes when loading, the buffer does send all 3 pairs and carriage return (ASCII 10). But not sure if this is the problem.

So far, the code plots 3 or maybe 4 sets , then stops. I like to Dynamic plotting of the data stream from Arduino

The code of the Arduino sketch is below. It is a modification of the original to print 3 sensor readings.

#include <Wire.h>
#include "Adafruit_AS726x.h"

//create the object
Adafruit_AS726x ams;

//buffer para leer valores en bruto  
uint16_t sensorValues[AS726x_NUM_CHANNELS];

//buffer para  guardar los valores calibrados( no esta siendo utilizado en este codigo)
//float calibratedValues[AS726x_NUM_CHANNELS];

void setup() {
  Serial.begin(9600);
  while(!Serial);
  
  // inicializa el pin digital LED_BUILTIN como un output.
  pinMode(LED_BUILTIN, OUTPUT);
  
  //inicia y permite la comunicacion con el sensor 
  if(!ams.begin()){
    Serial.println("could not connect to sensor! Please check your wiring.");
    while(1);
  }
}

void loop() {

  //lee la temperatura del sensor
  uint8_t temp = ams.readTemperature();
  
  //ams.drvOn(); // descomentar esto si quieres usar el led del sensor para hacer medidas
  ams.startMeasurement(); //begin a measurement
  
  //permite que el sensor lea la data cuando este disponible 
  bool rdy = false;
  while(!rdy){
    delay(1000);
    rdy = ams.dataReady();
  }
  //ams.drvOff(); //descomentar esto si quieres usar el led del sensor para hacer medidas

  //lee los valores!
  ams.readRawValues(sensorValues);
  //ams.readCalibratedValues(calibratedValues);

   //Serial.print("{");
  //Serial.print("Temp: "); 
  //Serial.print(temp);
  //Serial.print(",");
  //Serial.print(" Violet: ");
  //Serial.print(sensorValues[AS726x_VIOLET]);
   //Serial.print(",");
  //Serial.print(" Blue: "); 
  Serial.print(sensorValues[AS726x_BLUE]);
   Serial.print(",");
  //Serial.print(" Green: "); 
  //Serial.print(sensorValues[AS726x_GREEN]);
   //Serial.print(",");
  //Serial.print(" Yellow: ");
   Serial.print(sensorValues[AS726x_YELLOW]);
    Serial.print(",");
  //Serial.print(" Orange: ");
  //Serial.print(sensorValues[AS726x_ORANGE]);
   //Serial.print(",");
  //Serial.print(" Red: "); 
  Serial.print(sensorValues[AS726x_RED]);
  //Serial.print("}");
   
  Serial.println();
  //Serial.println();
  
delay(400);
}

Here my resultsenter image description here

FOLLOW-UP #2

After applying @wvt_beginner feedback and comment, the delay where removed from the Arduino Code. The reading of the stream is stabled but it serial closes after 3 or 4 data sets delivered.

Illustrations of Arduino Sketch and WM Notebook results.

Follow-up Update 2:

So, found out that the problem had nothing to do with the code, but with Mathematica. Was running version 11.2 . I first mover the rawReadings = {} line to before the parseData function. There , I noticed that the serial port pick up 7 and 8 dataset. Give me the idea that maybe potentially a problem with the compilation.

I upgraded to WM version 13.1 and the Dynamic is picking up with a continuous readings.

I am still having problemns with the serial. I ented the run with CNTL+c then restarted teh otebook. I am getting failure.

UPDATE 3

So far, I applied the option or removing and replacing teh Delay() with a timer loop. But I am getting 0 readings. It looks possibly a problem with the way the variable have been set up. Here is the updated code. BUT only returns 0 readings.

Here is the SKETCH

    #include <Wire.h>
#include "Adafruit_AS726x.h"
//create the object
Adafruit_AS726x ams;
//buffer para leer valores en bruto
uint16_t sensorValues[AS726x_NUM_CHANNELS];
//buffer para  guardar los valores calibrados( no esta siendo utilizado en este codigo)
//float calibratedValues[AS726x_NUM_CHANNELS];


void setup() {
  Serial.begin(115200);

  while (!Serial)
    ;

  // inicializa el pin digital LED_BUILTIN como un output.
  pinMode(LED_BUILTIN, OUTPUT);

  //inicia y permite la comunicacion con el sensor
  if (!ams.begin()) {
    Serial.println("could not connect to sensor! Please check your wiring.");
    while (1)
      ;
  }
}

void loop() {

  //lee la temperatura del sensor
  //uint8_t temp = ams.readTemperature();

  //ams.drvOn(); // descomentar esto si quieres usar el led del sensor para hacer medidas
  ams.startMeasurement();  //begin a measurement

  //permite que el sensor lea la data cuando este disponible
  bool rdy = false;
  while (!rdy) {
    delay(5);
    rdy = ams.dataReady();
  }
  //ams.drvOff(); //descomentar esto si quieres usar el led del sensor para hacer medidas

  //lee los valores!
  ams.readRawValues(sensorValues);
  //ams.readCalibratedValues(calibratedValues);

  //Serial.print("{");
  //Serial.print("Temp: ");
  //Serial.print(temp);
  //Serial.print(",");
  //Serial.print(" Violet: ");
  Serial.print(sensorValues[AS726x_VIOLET]);
  Serial.print(",");
  //Serial.print(" Blue: ");
  Serial.print(sensorValues[AS726x_BLUE]);
  Serial.print(",");
  //Serial.print(" Green: ");
  Serial.print(sensorValues[AS726x_GREEN]);
  Serial.print(",");
  //Serial.print(" Yellow: ");
  Serial.print(sensorValues[AS726x_YELLOW]);
  Serial.print(",");
  //Serial.print(" Orange: ");
  Serial.print(sensorValues[AS726x_ORANGE]);
  Serial.print(",");
  //Serial.print(" Red: ");
  Serial.print(sensorValues[AS726x_RED]);
  //Serial.print("}");

  Serial.println();
  ;
}
$\endgroup$
6
  • 1
    $\begingroup$ Serial port is not connected. Cannot advise on this one. The label true is in blue color which is an undefined quantity yet. Try True instead. Also the double underscores in the function definition can match more than one input, try to use a single underscore for each. Also try the Arduino SE site for a better chance at getting this resolved. $\endgroup$
    – Syed
    Sep 20, 2023 at 3:19
  • $\begingroup$ Consider: If rawReadings = {{50, 50, 44, 53, 53, 50, 44, 51, 54, 13}, {50, 50, 44, 53, 51, 44, 51, 54, 13}, {50, 49, 44, 53, 50, 44, 51, 54, 13}} then SequenceSplit[#, {44}] & /@ rawReadings would give the desired result. $\endgroup$
    – Syed
    Sep 20, 2023 at 3:27
  • $\begingroup$ @Syed Thank you. This help mitigating getting errors from feeds. But the code continues to close the Serial connection after three readings. The second suggestion using SequenceSplit[] , not sure where exactly the suggested modification applies to where . $\endgroup$ Sep 20, 2023 at 11:02
  • $\begingroup$ I believe the code for parseData is trying to get values separated by the commas. This function is where the code will go as the example in my comment suggests. Please post code. Please explain how test1 came about from rawReadings as I cannot see how. The second definition of parseData matches anything at all, so I suggest that you comment it out temporarily and check the effect of doing so. Reduce line speed or verify signal quality on Rx/Tx using a scope. Best of luck. $\endgroup$
    – Syed
    Sep 20, 2023 at 11:41
  • $\begingroup$ #Syed . Thank yo for your suggestion son using the Arduino SE channel. But that group. But that group profile struggles with issues anything requiring advanced integrations. $\endgroup$ Sep 21, 2023 at 3:04

1 Answer 1

3
$\begingroup$

Get rid of the delay(1000) and delay(400) statements in your arduino code. Delay has blocking behaviour. Take a look at the examples -> blink without delay. The delay(1000) statement inside the while construction makes no sense to me. it blocks the whole code execution for 1000ms while the boolean variable rdy may have changed to true.

EDIT 1: Ok, here is a minimum working example for you. Since I do not have access to the Adafruit sensor I will use some dummy random numbers and transfer these via Serial. It sends that data every 250ms.

unsigned long previousMillis = 0;  
const long interval = 250;  
int myArray[3];
const int number=100;
bool send=false;

void setup() {
Serial.begin(115200);
}

void loop() {
  unsigned long currentMillis = millis();
  for(byte i=0;i<3;i++){
    myArray[i]=random(-20,20);

  }
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    send=true;    
    }
  if (send){
    Serial.print("{");
    Serial.print(number+myArray[0]);
    Serial.print(",");
    Serial.print(number+myArray[1]);
    Serial.print(",");
    Serial.print(number+myArray[2]);  
    Serial.println("}"); 
    send=false;    
  }

  }

To process the data being sent try the following on the Mathematica side:

dev = DeviceOpen["Serial", "COM3"]

rawReadings = {}

task = RunScheduledTask[
rawReadings = {rawReadings, DeviceReadBuffer[dev, 3]};
rawReadings = Partition[Flatten@rawReadings, 3], 0.05]

ListLinePlot[Transpose[rawReadings],PlotLegends -> Automatic] 
//Dynamic

RemoveScheduledTask[task]
DeviceClose[dev]
   
$\endgroup$
2
  • $\begingroup$ Thank you for your contribution. But this made no difference. I tested isolating delay 400 , 1000 and both together. but same. These delays contributes to allow time to the sensor internal processing delays to deliver readings. $\endgroup$ Sep 20, 2023 at 0:43
  • $\begingroup$ That makes no sense at all, delay blocks the whole code execution on your arduino. In your while loop you are waiting for a flag ams.dataReady() to be set to true; this will NOT be evaluated until delay(1000) has elapsed, regardless if your sensor has data ready to process by your Arduino or not. Get that fixed first. $\endgroup$ Sep 22, 2023 at 12:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.