0

so I am having trouble sending data using software serial's write function.

TX Code:

#include <SoftwareSerial.h>

SoftwareSerial TX(2,3); 

void setup() { 
  // put your setup code here, to run once: 
  TX.begin(1200); 
} 

void loop() { 
    TX.write(60);  
}

Is the delay necessary?

RX Code:

#include <SoftwareSerial.h>
SoftwareSerial RX(2,3); //(rx pin, tx pin)
const unsigned int bufferSize = 100;

void setup() { 
  Serial.begin(9600); 
  RX.begin(1200); 

}

void printBuffer(const uint8_t *serialBuffer)
{
  //print contents of buffer
  for (int i = 0; i<100; i++) 
    Serial.println(serialBuffer[i], BIN);
}

void processBytes(const uint8_t value)
{ 
  static uint8_t serialBuffer[bufferSize]; //buffer to hold values
  static unsigned int startPosition=0;

  if(startPosition < bufferSize)
    serialBuffer[startPosition++] = value; 

  else
  {
    printBuffer(serialBuffer);
    startPosition = 0;
  }

}//end of processBytes
void loop() { 

  //check if data is available in serial buffer
  while(RX.available())
  {
    //process data
    processBytes(RX.read());
  }   
}

If i transmit the number 60, it prints 226 constantly for 2-3 seconds, then prints 60 for a short while, then goes back to printing 226. Am I doing something wrong with my code?

FIRST QUESTION: In the case when startPosition (in the process function) equals 100, it will call print. Print will then print 100 integers. Now, when doing that, there could still be data being transmitted from the transmitter. But the read function won't be executed until printBuffer returns, process returns, and the while loop iterates again. So during that time, couldn't some transmitted values potentially not be read?

SECOND QUESTION How come Software serial doesn't synchronize incorrectly more often? How is it being so accurate if the start bit is just a single bit and it's a 0. So for instance, if payload has some 0s, how come one of those 0s aren't being assumed to be the startbit? How does this get resolved? I looked at the software serial library, but I am not able to find out why. Any guidance here?

THIRD QUESTION Other than getting the startbit syncing right, are there other ways to sync the data? I was reading of NRZ encoding, manchester encoding, etc. Can any of these be implemented here? Also, would it be wise to alter the softwareSerial library to have more than one startbit?

Any guidance would be very appreciated! Thank you so much! This is all being done with wireless RF modules.

Jonathan
  • 264
  • 2
  • 14
  • 1
    Q2: RS232 serial idles high (aka Mark state). A transition to low (aka Space state) signals the beginning of a frame. It is assumed (read: part of the spec) that the two systems' clocks accurate enough to stay well-enough synced for the duration of a frame. Q3: There are other serial protocols including synchronous ones, and others could probably be adapted. But what problem are you trying to solve by doing so? – JRobert Oct 25 '15 at 17:42
  • Q2: Sorry I am mistaken, but isn't RS232 for wired connection mostly? And since this is wireless, i believe it idles low? Plz correct me if I am wrong. I could be mistaken. Also, when transmitting at high speeds, the device doesn't have that much time to "idle" at either state, because the next frame will already begin to transmit right? – Jonathan Oct 25 '15 at 18:25
  • Q3: The reason I am trying to use UART instead of synchronous communication is, synchronous utilizes a clock signal which is constantly being sent, therefore there will be greater battery consumption and the bandwidth might not be fully utilized for the data frame. My end result is to have a very very battery efficient mesh network using RF modules that works efficiently even when placed amidst medium disturbance(using error correction code) and is able to transmit large data packets quickly. I want it to be cost-effective and power-effective. I am demoing it on these modules first. – Jonathan Oct 25 '15 at 18:29
  • `And since this is wireless, i believe it idles low?` - whether or not it is wireless is irrelevant. Why do you believe this? – Nick Gammon Oct 26 '15 at 19:43
  • `How come Software serial doesn't synchronize incorrectly more often? How is it being so accurate if the start bit is just a single bit and it's a 0. So for instance, if payload has some 0s, how come one of those 0s aren't being assumed to be the startbit?` - because there should be a nice big gap between the start of a transmission (which your sending code does not now have). Assuming you have a gap long enough, the first 0 will be the the start bit, it then clocks in 8 characters, and then the stop bit, which is a 1, which makes sure that you don't mistake it for another start bit. – Nick Gammon Oct 26 '15 at 19:44
  • Once the byte starts being received, any internal 0 bits are not considered start bits. Read [my page about serial comms](http://www.gammon.com.au/forum/?id=10894) - you seem to not understand the process in general. `Also, would it be wise to alter the softwareSerial library to have more than one startbit?` - no, because you would then have no alternative but to ignore the second one. You are thrashing around with these suggestions. – Nick Gammon Oct 26 '15 at 19:46
  • `I was reading of NRZ encoding, manchester encoding, etc.` - certainly there are other ways of transmitting data, remote controls and remote-controlled vehicles use other methods than serial. This now is making this question extremely broad. – Nick Gammon Oct 26 '15 at 19:47
  • The "idles low" comment was w/ respect to the comment by JRobert, and before I actually had some amount of delay in the TX code. But is there a methodical way to estimate exactly how much the delay should be? And for the "longer start sequence" suggestion, I read that often times the start bit is actually a sequence, not just 1 bit. In a separate post, someone told me that exactly. That, typically, it's longer than just a bit. – Jonathan Oct 27 '15 at 03:19
  • For the synchronization question, I wanted to get a feel of how to implement such a thing, regardless of if it will be apt. Specifically NRZ encoding. Sorry! I really don't mean to sound ignorant or rude. Please forgive my foolishness. I will do more reading on serial comm. – Jonathan Oct 27 '15 at 03:19
  • Also if ample gap is what is required the start bit to be correctly recognized, then why is there the following scenario. I had asked this in a pervious question regarding delays. But to reiterate, when I transmitted with delays of microseconds, it was very low error rate, and delay of 3 or more was more error. And I read your explanation on the error rate based on how long NOP instructions take and the rounding down of the delay time/instruction time. However, based on the comment that you informed me now, shouldn't 3 microsecond delay potentially give better results? – Jonathan Oct 27 '15 at 04:39
  • @NickGammon Hello, should i make the above questions a new question? – Jonathan Oct 29 '15 at 17:53
  • `In a separate post, someone told me that exactly.` - where did they say that? Link? The start bit has to be exactly one bit length or the timing of everything else would be out. – Nick Gammon Oct 29 '15 at 19:43
  • 1
    `should i make the above questions a new question?` - your question about Manchester and NRZ vs Serial should be a new question, certainly. And your questions about start bit length seem to me to be another question again. This question started off being about "why doesn't this code work?" and is now morphing into "how does serial comms work, exactly?". – Nick Gammon Oct 29 '15 at 19:45

1 Answers1

2
void loop() { 
  Serial.println("NEW-------------");
  int x;
  int y[100];
  for(int i = 0; i<100; i++){ 
    x=RX.read(); 
    y[i] = x;
  } 
...
}

You are reading data without checking if there is any data there. That's like watching the TV without checking if it is turned on. Of course you get weird data.


SoftwareSerial RX(0,1); //(rx pin, tx pin)

Pins 0 and 1 are used by HardwareSerial. Why are you using them for SoftwareSerial?


SoftwareSerial RX(0,1); //(rx pin, tx pin)
...

  Serial.begin(9600); 
  RX.begin(1200); 

So you initialized HardwareSerial, which now controls pins 0 and 1.

Then you try to initialize SoftwareSerial on those same pins! Would you mind explaining why?

Whatever your explanation is, it won't work.


I've added in the changes you mentioned, but the data still seems to be skewed.

You've changed things, for sure:

 for(int i = 0; i<100; i++){ 
    if(RX.available())
      x=RX.read(); 

    y[i] = x;
    }

Let's see. In a loop of 100 iterations you see if anything is available (and if so, put it into x).

Then, regardless of whether or not you got anything you now assign x to y[i]. So, most of the time, y[i] will have garbage in it.

the data still seems to be skewed

Not surprised. Do it differently. Only write to the array if you have data. In fact you may want a complete rework. Read this:

How to read serial without blocking


I have posted the amended code. Change: Only add to the array is data is being read from buffer.

  int y[100];
  for(int i = 0; i<100; i++){ 
    if(RX.available())
    {
      x=RX.read(); 
      y[i] = x;
    }
  } 

 for (int j = 1; j<=64; j++){ 
    Serial.println(y[j]);
  } 

You still have not fixed it. Let me talk you through what it is doing now.

You are making 100 attempts to read some data. One or two may succeed, and they will be put into the buffer y (funny name for a buffer, right?).

So imagine . is garbage and X is good data, after doing that loop of 100 the buffer will look like this:

........X...........X...........X...X......................X.............................................

So your buffer is still 80% unchanged garbage. Then you print the first 64 elements (why 64 and not 100?) and you get a lot of garbage out. Exactly as expected.


You need to think about what you are doing. Draw it out on a bit of paper, perhaps.

Here is some example code from the page I linked for you, more than once. Please compare:

// how much serial data we expect before a newline
const unsigned int MAX_INPUT = 50;

void setup ()
  {
  Serial.begin (115200);
  } // end of setup

// here to process incoming serial data after a terminator received
void process_data (const char * data)
  {
  // for now just display it
  // (but you could compare it to some value, convert to an integer, etc.)
  Serial.println (data);
  }  // end of process_data

void processIncomingByte (const byte inByte)
  {
  static char input_line [MAX_INPUT];
  static unsigned int input_pos = 0;

  switch (inByte)
    {

    case '\n':   // end of text
      input_line [input_pos] = 0;  // terminating null byte

      // terminator reached! process input_line here ...
      process_data (input_line);

      // reset buffer for next time
      input_pos = 0;  
      break;

    case '\r':   // discard carriage return
      break;

    default:
      // keep adding if not full ... allow for terminating null byte
      if (input_pos < (MAX_INPUT - 1))
        input_line [input_pos++] = inByte;
      break;

    }  // end of switch

  } // end of processIncomingByte  

void loop()
  {
  // if serial data available, process it
  while (Serial.available () > 0)
    processIncomingByte (Serial.read ());

  // do other stuff here like testing digital input (button presses) ...

  }  // end of loop
Nick Gammon
  • 35,792
  • 12
  • 63
  • 121
  • It seems to be a common misconception that you have to use software serial to talk on the TX and RX pins, and that your computer communicates with the main chip through eTelepathy. I wish people would read the manual! – Majenko Oct 20 '15 at 11:34
  • Hello sir, so i looked at your forum. At such high baud rates, the read would execute extremely fact but for ProcessIncomeBytes to execute, it would take longer than the speed at which read is reading right? and whwat else should i rework? i fixed the array part. – Jonathan Oct 22 '15 at 05:42
  • 1
    I don't understand any of that. The read would be faster than the read? If you fixed some code please post the amended code. At 9600 baud I would not be too worried about code execution time. – Nick Gammon Oct 22 '15 at 19:52
  • What I mean is, processIncomingBytes is called and immediately, read is also called. Then the return of read is being sent to procsessIncomingBytes. Now, processIncomingBytes will execute it's algorithm, and during that time, bits are still being sent to the buffer of the receiver. But read is not being called. So isn't there a possibility of some bytes potentially being lost if the buffer goes into overflow? Maybe not for 9600 baud, but what if i had 115200 baud? I have posted the amended code. Change: Only add to the array is data is being read from buffer. – Jonathan Oct 23 '15 at 02:44
  • 1
    Well, it won't go into overflow if you code correctly. Take a look at my [MIDI interpreter demo (video)](https://vimeo.com/80328016). That is using SoftwareSerial reading at 31250 baud, interpreting it, and outputting the converted output to the screen. You can see from the video it keeps up with very fast MIDI. Please read my link [How to read serial without blocking](http://www.gammon.com.au/serial). – Nick Gammon Oct 23 '15 at 04:57
  • See amended reply. – Nick Gammon Oct 23 '15 at 20:39
  • Sorry, I didn't mean to seem like I didn't look at your link. I did look at it, and the other one you posted before hand of how to do serial communication. I just didn't quite understand. Sorry! I will try to learn it again. Thank you for your help! – Jonathan Oct 24 '15 at 04:17
  • Also my thinking behind why I am only printing 64 was because, the buffer only holds 64 bytes. – Jonathan Oct 24 '15 at 04:19
  • `int y[100];` - how can you say it only holds 64 bytes? – Nick Gammon Oct 24 '15 at 05:00
  • In your code, you have up to the first 50 bytes, then if it's overflow, we empty buffer, or if end line character is reached, then we process/print bytes. But the 50 bytes could potentially have lots of garbage right? So is the change you're implying in my code, what i have implemented (see modified question)? Also, there is only 64 byte serial buffer built for the UART built into the chip, which is why i had 64. But I see why that doesn't matter. – Jonathan Oct 25 '15 at 09:28
  • @NickGammon I have editted my question. – Jonathan Oct 26 '15 at 07:50