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.

  • 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
  • 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
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
  • 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 5: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 2:44
  • 1
    Well, it won't go into overflow if you code correctly. Take a look at my MIDI interpreter demo (video). 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. – Nick Gammon Oct 23 '15 at 4:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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