0

So I have a program that works great on the Mega, it uses serial 3 to read and streams out to the USB (I posted a previous question which someone answered) I tried to use Serial (D0) to read and then write to serial, which did not work. So now I am looking in to Software Serials

Is there a difference between a real serial and software serial as it does not seem to be working, It all runs a bit slower

#include <SoftwareSerial.h>

const int DesiredRPM=300;  // Setting Desired RPM Here.
const int MotorPWMPin=4;
int inByte = 0;         // incoming serial byte
unsigned char Data_status=0;
unsigned char Data_4deg_index=0;
unsigned char Data_loop_index=0;
unsigned char SpeedRPHhighbyte=0; // 
unsigned char SpeedRPHLowbyte=0;

int SpeedRPH=0;
const unsigned char PWM4dutyMax=255;
const unsigned char PWM4dutyMin=100;
unsigned char PWM4duty=PWM4dutyMin;  // have to set a default value make motor start spining


SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
    pinMode(MotorPWMPin, OUTPUT); 
    Serial.begin(115200);  // USB serial
    Serial3.begin(115200);  // XV-11 LDS data 

    // prints title with ending line break 
    Serial.println("Arduino Neato XV-11 Motor control board v0.1 by Cheng-Lung Lee"); 

    // Pick your magic number and drive your motor , 178 is 178/255*5V=3.49V
    analogWrite(MotorPWMPin, PWM4duty );  

    mySerial.begin(115200);
}

void loop() {
    // if we get a valid byte from LDS, read it and send it to USB-serial
  if (Serial3.available() > 0) {
    // get incoming byte:
    inByte = Serial3.read();
    //Serial.print(inByte, BYTE);
    //Serial.write(inByte);
    Serial.print((char)inByte);
    decodeData(inByte);
  }

  if (mySerial.available() > 0) {
    // get incoming byte:
    inByte = mySerial.read();
    //Serial.print(inByte, BYTE);
    //Serial.write(inByte);
    Serial.print((char)inByte);
    decodeData(inByte);
  }

}

void decodeData(unsigned char inByte){
  switch (Data_status){
  case 0: // no header
  if (inByte==0xFA)
  {
    Data_status=1;
    Data_loop_index=1;
  }
    break;
  case 1: // Find 2nd FA
    if (Data_loop_index==22){
      if (inByte==0xFA)
      {
        Data_status=2;
        Data_loop_index=1;
      } 
      else // if not FA search again
      Data_status=0;
    }
    else{
      Data_loop_index++;
    }
    break;
  case 2: // Read data out

     if (Data_loop_index==22){
      if (inByte==0xFA)
      {
        Data_loop_index=1;
      } 
      else // if not FA search again
      Data_status=0;
    }
    else{
      readData(inByte);
      Data_loop_index++;
    }
    break;
  }

}
void readData(unsigned char inByte){
  switch (Data_loop_index){
    case 1: // 4 degree index
    Data_4deg_index=inByte-0xA0;
//      Serial.print(Data_4deg_index, HEX);  
//      Serial.print(": ");  
    break;
    case 2: // Speed in RPH low byte
    SpeedRPHLowbyte=inByte;
    break;
    case 3: // Speed in RPH high byte
    SpeedRPHhighbyte=inByte;
    SpeedRPH=(SpeedRPHhighbyte<<8)|SpeedRPHLowbyte;

    SpeedControl ( DesiredRPM ) ; // 
//      Serial.print(SpeedRPHhighbyte, HEX);   
//      Serial.println(SpeedRPHLowbyte, HEX);   
    break;
    default: // others do checksum
        break;
  }  
}


// Very simple speed control
void SpeedControl ( int RPMinput)
{
 if (Data_4deg_index%30==0) {  // I only do 3 updat I feel it is good enough for now
  if (SpeedRPH<RPMinput*60)
     if (PWM4duty<PWM4dutyMax) PWM4duty++; // limit the max PWM make sure it don't overflow and make LDS stop working
  if (SpeedRPH>RPMinput*60)
     if(PWM4duty>PWM4dutyMin) PWM4duty--;  //Have to limit the lowest pwm keep motor running
  }     
  analogWrite(MotorPWMPin, PWM4duty ); // update value
}
2

There are huge differences. The most important ones are:

  • SoftwareSerial is half duplex (it can send or it can receive, it cannot do both at once)
  • SoftwareSerial is blocking - while it is sending or receiving nothing else can happen

SoftwareSerial is very much a poor-man's serial port. It should only really be used for very low volume data (things like NEMA messages once a second or so) and only if you have absolutely no choice (and, let's face it, you always have a choice).

  • Ok thank you, damn I need 2 serial ports then. I read on the serial and send on to USB. – Burf2000 Nov 28 '16 at 23:07
  • That is often the case. That is why Atmel came up with the "upgrade" of the ATMega328PB which has a second UART. Another good choice is the ATMega32U4 (as used on the Leonardo) which separates the USB from the UART so you can use both separately. – Majenko Nov 28 '16 at 23:08
  • Oh brilliant, I only need it for this project, so I should get a Leonardo, hopefully it's smaller than the mega – Burf2000 Nov 28 '16 at 23:10
  • It's the same footprint as the Uno. – Majenko Nov 28 '16 at 23:10
  • Thanks you :) out of scope I know but any down point? Like not compatible with shield etc. Assuming the Leonardo uses serial1 – Burf2000 Nov 28 '16 at 23:11

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.