Arduino: Sensor sending two different data at the same time

Hi all

I am trying to use values from a grove sensor connected to an Arduino board. This sensor sends humidity and temperature data.
From this video https://www.youtube.com/watch?v=_NpivsEva5o I have this code:

(
~charArray = [ ];
~getValues = Routine.new({
	var ascii;
	{
		ascii = ~port.read.asAscii;
		if(ascii.isDecDigit, {~charArray = ~charArray.add(ascii)});
		if(ascii == $a, {
			~val = ~charArray.collect(_.digit).convertDigits;
			~charArray = [ ];
		});
	}.loop;
}).play;
)

This way I can read out humidity for example, but I couldn’t figure out how to read out temperature at the same time.

Thanks!

You’d need a delimiter on the sending side:

Serial.print(humidity);
Serial.print(";");
Serial.print(temperature);
Serial.print("a");
// ^^ or however you're currently breaking lines

Then ; in the input stream means the preceding digits are humidity, and a means it’s temperature.

In general terms, this is “serialization.”

hjh

Yes, I assumed so.
I am just a bit stuck on how to write a working SC code for that. This is obviously not going to work:

(
~charArray_01 = [ ];
~charArray_02 = [ ];
~getValues = Routine.new({
	var ascii;
	{
		ascii = ~port.read.asAscii;
		if(ascii.isDecDigit, {~charArray_01 = ~charArray_01.add(ascii)});
		if(ascii == $a, {
			~val_01 = ~charArray_01.collect(_.digit).convertDigits;
			~charArray_01 = [ ];
		});
		if(ascii.isDecDigit, {~charArray_02 = ~charArray_02.add(ascii)});
		if(ascii == $;, {
			~val_02 = ~charArray_02.collect(_.digit).convertDigits;
			~charArray_02 = [ ];
		});
	}.loop;
}).play;

The missing element is that you need two levels of looping, but you’re trying to do it with only one.

The algorithm should read:

  1. Collect characters into an array as long as they are decimal digits – this may comprise multiple digits, so it must be an inner loop, which is most easily expressed by while.

    while {
        ascii = ~port.read.asAscii;
        ascii.isDecDigit
    } {
        charArray = charArray.add(ascii);
    };
    
  2. After this, ascii will be a non-digit. Use this character to decide which value is set.

    value = charArray.collect(_.digit).convertDigits };
    switch(ascii)
    { $a } { ~val_01 = value }
    { $; } { ~val_02 = value }
    

And all of that runs in an outer loop.

This way, you need only one charArray. Also, charArray is properly local.

(
~charArray_01 = [ ];
~charArray_02 = [ ];
~getValues = Routine.new({
	var ascii, charArray, value;
	loop {
		while {
			ascii = ~port.read.asAscii;
			ascii.notNil and: { ascii.isDecDigit }
		} {
			charArray = charArray.add(ascii);
		};
		value = charArray.collect(_.digit).convertDigits;
		charArray = nil;  // EDIT: Need to clear the list!
		switch(ascii)
		{ $a } { ~val_01 = value }
		// (or maybe 'b' would make more sense here?)
		{ $; } { ~val_02 = value };
	};
}).play;
)

hjh

That’s it. Thanks a lot!