Please advise me on my first Arduino Serial project

Hi,
I need help getting started with my first bit of Arduino code.

I have a Basic Stamp device that generates 20 consecutive bytes of RS-232 data. It then goes and processes another set and then repeats the 20 byte data stream.

I would like to use one of the Chinese Pro Micro Leonardo Arduino devices that has the built in USB port. I have it working on the bench and I can upload and talk to it. That works.

I have been reading the pages here and I fear until I actually start writing my own code, I will just continue to be confused.

I now have my Basic Stamp generating a recirculating 20 byte serial string. There is a nice amount of time between each 20 byte transmission. The baud rate is 38400. I have a proper RS232 Receiver connected to the RXD pin on my Pro Micro Leonardo and I can see the TTL data flying in on the Arduino pin with my scope.

** Here is what I would like to do…

I would like to have a program that reads the incoming serial and stores it in variables in the Arduino.

I would then like to send the decimal or binary value of some or all of the selected bytes to the monitor and have it formatted like:

Variable00 = 256 "
Variable01 = 145
Variable02 = 127

Or perhaps:

Variable00 = 11111111
Variable01 = 01111111

Etc.

Once I have mastered this, I can then learn how to select certain values from given variables to operate a relay, LED or perform some other function.

Here is what I understand…
During Void Setup:

Serial.begin(9600) // set baud rate for Monitor
Serial1.begin(38400) // set baudrate or incoming built in serial port
byte DataString[20] \ set an array to hold 20 bytes of data

During Void Loop:

Serial1.available(==>20) // part of an if statement to get the processing started
Serial.print("Variable 01 is: "); //print some ascii to the monitor so I know what I am seeing
Serial.print(DataString.Variable01); //Print the variable to the serial monitor

Keep doing the above with other variables.

Of course I need to obey the syntax of Arduino and I am beginning to understand that. I am just hoping that someone here will take me under their wing and help me get started.

Greg

Suggest you spend some time reading this Serial Input Basics

Thanks -- I have read that post and it is an excellent overview.

However, it largely deals with Ascii and Text data. I just have a string of 20 changing values, 0 to 255

I also miss when and how I an move binary data out of the serial buffer and into variables. Should I use an array or can I easily load 20 variables?

Thanks

Greg

For testing purposes get your Basic Stamp to send printable characters. Also get it to send the same data repeatedly. It will make the debugging very much easier.

Then ....

  • Tell us what data the Stamp is sending.
  • Post your Arduino program.
  • Tell us exactly what the Arduino program does and what you want it to do that is different.

...R

Use an array with 20 bytes. Each time a byte arrives, store it in the next position in the array. I think the variable for that in robin's tutorial is called ndx. Once 20 bytes are received, reset ndx.

You probably want a means of synchronisation, possibly a timeout. Your stamp is sending data and next you switch the arduino on. The first byte it sees might actually be the 5th byte that the stamp is sending.

Then you have crap. With no start or end marker there's no reliable way to detect the start of the first data value.

Of course you can load 20 variables. But if they have names like var1, var2, var3... then you definitely should have used an array.

How long between messages?

byte DataString[42];  // set an array to hold at least two 20 byte messages


void setup()
{
  Serial.begin(115200);  // set baud rate for output (Serial Monitor) much higher than input rate
  Serial1.begin(38400);  // set baudrate for incoming built in serial port


  Serial1.setTimeout(100);  // Set the timeout in milliseconds.  Must be shorter than the time between messages
}


void loop()
{
  size_t count = Serial1.readBytes(DataString, 42);
  Serial.print("Bytes read: ");
  Serial.print(count);
  Serial.print(": ");
  for (size_t i = 0; i < count; i++)
  {
    Serial.print(DataString[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

Let me try to answer the last three replies.

My Basic Stamp system sends 20 bytes of data in a stream. Most of it is 8 bit numbers from an A to D Converter.

The Stamp waits 150ms then sends a new batch of data. This runs continuously.

I am new to Arduino programming. I have downloaded several sample programs and changed a few things. I have never written anything for Arduino. I have written a bunch of stuff in pBasic for the Stamp, including the program that is sending the data I am trying to read.

My project is a control and monitoring system for a large 1/8th scale train. 8th scale means I can ride on the train. The engine has a system that monitors a bunch of conditions and sends them down a serial line.

One of the things I do is watch for certain data conditions and turn on a light, or close a relay.

I wanted to start learning Arduino so I thought my first project would be to receive this data stream I call 'NemoString", look for certain data conditions and turn on a relay or an LED.

For my first step, I thought I should try to select one of the bytes from the data stream and display the decimal value on the Arduino Monitor.

At a suggestion from Robin2, I switched over to an Leonardo so I would have a separate serial port. That is done and working. I can see the serial data on the RXD pin with my scope.

Here is the beginning of my code. Please don't laugh. I am trying here.

void setup() {
  // Setup Serial Ports
  Serial.begin(9600); //This is the USB Port
  Serial1.begin(34800)  //This is the Basic Stamp Serial
  
  int NemoString[20]    // Make a 20 byte Array
  

}

void loop() {

// I need something here to read Serial1 Port after 20 bytes have arrived and put the data in the array.

//  Now send the value of NemoString01 to the Arduino Monitor

Serial.print ("NemoString01 ");
Serial.print (NemoString[01]);


}

JohnWasser,

I was writing while you posted.

Thank You -- I will study your reply...

Greg

From the code in Reply #7

// I need something here to read Serial1 Port after 20 bytes have arrived and put the data in the array.

You could try this

byte numBytesAvail = Serial1.avallable();
if (numBytesAvail >= 20) {
   for (byte n = 0; n < numBytesAvail; n++) {
      byte inByte = Serial1.read();
      Serial.print(inByte);
   }
}

however it will not definitely get the correct set of bytes - some may be the residue of an earlier message. For reliability you need to surround the data with start- and end-markers. A simple way to do that is to prevent the STAMP from using the values 254 and 255 for data and just using those for the start- and end-markers. In which case the 3rd example in Serial Input Basics should work.

...R

...R

The 150ms delay can be taken to be the start marker. Use Robin2's excellent example code but every character received should reset the timer that holds the time the last char arrived.

If the current char is more than 100ms since the previous, clear the buffer and start the buffer fresh with this first char. When you get to 20 then you know you have the full message.

However it is usually easier if the data is readable while it is on the wire. A format like NMEA can be used that lets you connect the producer to a standard serial port and read the numbers on the Serial Monitor.

I am having some success with the johnwasser code. Thanks John! Its very exciting for me.

I have a pBasic device side by side so I can see when the numbers match up.

I don't understand why I am working with the number 42 instead of 20, but some experimentation will solve that.

Just having something work now inspires me and gives me a way to think about this.

I will test Robin2 code example as well. I also want to modify the code so it can isolate one piece of data.

I admit being resistant to using 255 as start and end bytes for some reason. I need to get over that. I always thought I might need to do it so my system already sends a 255 Start Byte. I reserved the last byte of the 20 so it is available also.

It is pretty easy in pBasic to insure that none of my data is over 254. Its just a bit of an ordeal to go back into that software I wrote 4 years ago.

Thanks everyone...

Greg

42 = (20+1) * 2

The reason for adding 1 is char[] strings in C add a special character on the end to show that it's the end. This character is '\0' which is actually zero in binary. However your (somewhat poorly-defined) format does seem to allow zeroes in the data, so you probably don't need this.

The reason for doubling it is to always make sure there's space available for the incoming data, even if something goes wrong and you miss the gap between two messages for some reason.

Worse, you might start looking at the data halfway through a 20-byte message. If you only scanned for 20 bytes then you would get the last 10 bytes of the previous message and the first 10 bytes of the next one. Even if you had some way of detecting that this is not a valid message, immediately starting to read 20 bytes will give you exactly the same result. It will never get back in sync.

I expect that John's example will work if you use 20 as the magic number. But as a quick test to make sure that there aren't extra characters being sent, it's useful.

The MODBUS serial protocol defines a maximum delay between characters. Even though it has start and end characters (and a checksum to check the data content) it also avoids rare problems like getting unplugged in the middle of a packet by also specifying the maximum gap between characters. If that gap is exceeded, the following character is assumed to be the start of a new packet.

gmcmurry:

void setup() {

// Setup Serial Ports
 Serial.begin(9600); //This is the USB Port
 Serial1.begin(34800)  //This is the Basic Stamp Serial
 
 int NemoString[20]    // Make a 20 byte Array
}

void loop() {

// I need something here to read Serial1 Port after 20 bytes have arrived and put the data in the array.

//  Now send the value of NemoString01 to the Arduino Monitor

Serial.print ("NemoString01 ");
Serial.print (NemoString[01]);

}

Note that NemoString is not a 20 byte array. It's a 20 int array. Also be aware that NemoString only will exist in setup() and will be unknow in loop(). You need to read up on variable scope

You probably want to declare NemoString outside setup() like

 byte NemoString[20]    // Make a 20 byte Array

void setup()
{
  // Setup Serial Ports
  Serial.begin(9600); //This is the USB Port
  Serial1.begin(34800)  //This is the Basic Stamp Serial
}

void loop()
{
}

NemoString will now be known in both functions

The monitor displays a fairly accurate version of what I know is being sent. I consider this a great accomplishment. I did it with your help.

My next task is to identify an individual byte so I can bit bash some results that can trigger an LED or RELAY.

I really don't want to use the monitor except for debugging.

I really want to turn on some LEDS or RELAYS based on what is happening in the 5th and 6th byte. Each bit in these bytes contain a control bit to turn on a light, horn, bell or some other function.

How do I isolate those bits?

Can I transfer them to another variable and then do logical math on them?

This is fun....
Greg

Bit maths is where C gets really useful and also somewhat unreadable. You can write an expression fully understanding what it does and then read it back and you don't know what it does. The bitwise-and operator looks very much like the logical-and operator. So you have to look extra hard sometimes to see which one is being used.

The code looks something like this...

const int NemoStringLength = 20;
byte Nemostring[NemoStringLength];
const int SpecialSwitchByte = 5; //select the 5th byte in the 20-byte message
const int HornBit = 6; //the horn on/off is set by bit 6 of the 5th byte. (Note that bits are numbered from zero.)
boolean soundHorn = false; //make this true to sound the horn

soundHorn = Nemostring[SpecialSwitchByte] & bit(HornBit);

The bit() macro takes the binary value 0b00000001 and left-shifts it by the desired amount to put a single "1" in whatever position you want. Another way of writing this is 1<<HornBit; The binary-and will then return a non-zero value if there is a corresponding bit in that position. Non-zero is true, so the boolean is set to true.

gmcmurry:
Hi,
I need help getting started with my first bit of Arduino code.

I have a Basic Stamp device that generates 20 consecutive bytes of RS-232 data. It then goes and processes another set and then repeats the 20 byte data stream.

I would like to use one of the Chinese Pro Micro Leonardo Arduino devices that has the built in USB port. I have it working on the bench and I can upload and talk to it. That works.

I have been reading the pages here and I fear until I actually start writing my own code, I will just continue to be confused.

I now have my Basic Stamp generating a recirculating 20 byte serial string. There is a nice amount of time between each 20 byte transmission. The baud rate is 38400. I have a proper RS232 Receiver connected to the RXD pin on my Pro Micro Leonardo and I can see the TTL data flying in on the Arduino pin with my scope.

** Here is what I would like to do…

I would like to have a program that reads the incoming serial and stores it in variables in the Arduino.

I would then like to send the decimal or binary value of some or all of the selected bytes to the monitor and have it formatted like:

Variable00 = 256 "
Variable01 = 145
Variable02 = 127

Or perhaps:

Variable00 = 11111111
Variable01 = 01111111

Etc.

Once I have mastered this, I can then learn how to select certain values from given variables to operate a relay, LED or perform some other function.

Here is what I understand…
During Void Setup:

Serial.begin(9600) // set baud rate for Monitor
Serial1.begin(38400) // set baudrate or incoming built in serial port
byte DataString[20] \ set an array to hold 20 bytes of data

During Void Loop:

Serial1.available(==>20) // part of an if statement to get the processing started
Serial.print("Variable 01 is: "); //print some ascii to the monitor so I know what I am seeing
Serial.print(DataString.Variable01); //Print the variable to the serial monitor

Keep doing the above with other variables.

Of course I need to obey the syntax of Arduino and I am beginning to understand that. I am just hoping that someone here will take me under their wing and help me get started.

Greg

Greg,

you are getting quite a load of helpful advise.
However, you "spec" is quite clear - receive 20 characters / bytes message every 150 mS and process it.

What is missing is - how long ( estimate) does it take for message such processing, perhaps change some outputs, to complete?

Can you afford to miss an incoming message?

A hint - even if the message processing is LONGER that 150 mS , your incoming data is relatively fast so collecting it using non blocking approach ( it will be suggested verbatim soon ) would be feasible but unnecessarily complicated.

Let the code do the work for you instead.

Hi,

I can easily do whatever I want to do in 150ms. And even if I couldn't, and had to skip a transmission, my system would be fine.

I need to identify certain bytes and send them an LCD display, some to a MAX7219 and some bytes will be used to simply turn on a set of relays or LEDs.

The system I am building will sit at the end of an RS232 cable where it will be displaying certain functions of a large scale locomotive.

There is a cpu that reads various locomotive conditions such as MPH, RPM, Air Pressure, etc. Along with a couple of bytes that give me 8 bits of Relays for things like "turn on the headlights" "blow the horn", and converts the data to to a bunch of 8 bit data.

All in there are 20 bytes. Byte 0 is unused and byte 19 is unused.

My system that sends the data is really slow because it uses Basic Stamp. Its just slow. When I look at the serial data on my scope, I can barely get it to trigger because there is so much time between data bursts. However, its still about 6 times a second which is fine for display updates, etc.

Bottom line is I am trying to improve my own programming skills, hence learn Arduino. I also want to work towards speeding the whole thing up.

This first project will allow me to build a small sub system with Arduino and slip it into my current Basic Stamp system. Then over time, I will upgrade the rest.

Its a fun project. Watch the Youtube above. There is a portion where you can see the control panel that I am trying to rebuild. It comes in at the bottom of the screen about half way through.

Greg

Greg,
thanks for reply.
I am little busy baby-sitting my grandkids now , but I'll put together some modular pseudo code ( I have no access to IDE) for you when I have a break.

gmcmurry:
All in there are 20 bytes. Byte 0 is unused and byte 19 is unused.

That's new. "Unused" as in they are start and end characters? If those values may appear in the real data then they aren't useful as start or end.

I think the 150ms space is all you need as a start marker.