NewSoftSerial on Lilypad 328 - wrong timing

Hello ... I'm trying to get data from GPS (LS20031, NewSoftSerial, 57600) on "LilyPad Arduino ATmega328" and getting garbage. When the same code is run on "Arduino Duemilanove ATmega328" it works perfectly fine.

  • Yes, I DO switch board names in Arduino IDE before programming the chip.
  • Yes, built in Serial works fine. ( eq. Serial.print("test!"):wink:
#include <NewSoftSerial.h>
NewSoftSerial mySerial(2, 3);
void setup()  
{
  Serial.begin(9600);
  mySerial.begin(57600);
}

void loop()
{
  if (mySerial.available()) {
      Serial.print((char)mySerial.read());
  }
  if (Serial.available()) {
      mySerial.print((char)Serial.read());
  }
}

Any ideas? Could it be an issue with NewSoftSerial ...?

Below are exempts from my boards.txt file.

##############################################################
lilypad328.name=LilyPad Arduino w/ ATmega328
lilypad328.upload.protocol=stk500
lilypad328.upload.maximum_size=30720
lilypad328.upload.speed=57600
lilypad328.bootloader.low_fuses=0xFF
lilypad328.bootloader.high_fuses=0xDA
lilypad328.bootloader.extended_fuses=0x05
lilypad328.bootloader.path=atmega
lilypad328.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
lilypad328.bootloader.unlock_bits=0x3F
lilypad328.bootloader.lock_bits=0x0F
lilypad328.build.mcu=atmega328p
lilypad328.build.f_cpu=8000000L
lilypad328.build.core=arduino

##############################################################
atmega328.name=Arduino Duemilanove or Nano w/ ATmega328
atmega328.upload.protocol=stk500
atmega328.upload.maximum_size=30720
atmega328.upload.speed=57600
atmega328.bootloader.low_fuses=0xFF
atmega328.bootloader.high_fuses=0xDA
atmega328.bootloader.extended_fuses=0x05
atmega328.bootloader.path=atmega
atmega328.bootloader.file=ATmegaBOOT_168_atmega328.hex
atmega328.bootloader.unlock_bits=0x3F
atmega328.bootloader.lock_bits=0x0F
atmega328.build.mcu=atmega328p
atmega328.build.f_cpu=16000000L
atmega328.build.core=arduino

The lilypad runs on 8Mhz iso 16MHz. NSS has diferent timeing tables for different CPU speeds.

The GPS runs @57600

Try NSS @115200 and @28800 (double speed/half speed)

If that works NSS uses the wrong table for the lily.

PLease let us know the results

Hello robtillaart,
thanks for quick reply. Neither speeds worked. So I tested them all -

#include <NewSoftSerial.h>
NewSoftSerial mySerial(2, 3);

void setup()  
{
  Serial.begin(9600);
  Serial.println("Lilypad NSS test");
  long sspd[] = {115200,57600,38400,31250,28800,19200,14400,9600,4800,2400,1200,300};

  for ( int x=0;x <10;x++){
  unsigned long start = millis();    
  mySerial.begin(sspd[x]);
  Serial.print("\nTesting at ");
  Serial.println(sspd[x]);

 while (millis() - start < 5000){
    if (mySerial.available()) {
          Serial.print((char)mySerial.read());
      }
  }
  mySerial.end();
  }
  Serial.print("\nEnd of testing.");
}

void loop()  
{
}

Responses I got are puzzling, especially that at 28800 I'm getting some kind of order (I mean NMEA line feeds are at right places).
Ever seen anything like that before?

puzzling indeed .... Great test by the way!

The fact that the line feeds are in the right place might hint that is the right frequency

Can you output in hexadecimal
Optionally mask the value with 0x7F - it looks like they all are high ascii values (just intuition)

Option divide value by 2 (shift one bit) ==> would indicate the startbit is missing/missed

robtillaart

I can output that in Hex, but I don't know how to

mask the value with 0x7

change the loop according to this ...

while (millis() - start < 5000)
{
  if (mySerial.available()) 
  {
    char c = mySerial.read() & 0x7F;
    Serial.print(c);
  }
}

After masking with 0x7F (why and what ...) 19200 looks better. What do you thing about contacting Mikal Hart?

do you have a snippet of correct output? what it should look like?
please also in hex .

I made interface cable to connect GPS device directly to PC, it worked and I was able to change speed from 57600 to 9600.
It worked :astonished:
So when GPS is transmitting at 9600 NSS is working correctly. I will test on other bauds as well.

Correct output should be NMEA string looking like those

$GAA1,,,,,,,,*E
$GPS311,0,68,4,1,4089,75,9,9,082272*8
$GGV321,23,3,9,0,0,261,62,54,,0,735*7
$GGV331,04,,2,2,6,33,7
GRC,0715.0,,655.1,,20.544,11,.0,2101,,*B
$GPVG00,,M,1.8,.9KN*30$GPGGA,071356.000,5656.0021,N,02402.5479,E,0,3,,126.3,M,23.8,M,,*41
$GPGLL,5656.0021,N,02402.5479,E,071356.000,V,N*4F
$GPGSA,A,1,,,,,,,,,,,,,,*E$GPGV311,0,684,1,4089,,75,9,0,082272*2
$GV321,23,3,9,0,0,261,62,54,,,735*7
$GGV331,04,1,2,2,6,33*7
GRC,075.0,,656.02,,20.547E11,.0,211,,*5
$GPVG00,,M,1.1,,.9KN*30$GPGGA,071357.000,5656.0038,N,02402.5481,E,0,3,,126.2,M,23.8,M,,*4E
$GPGLL,5656.0038,N,02402.5481,E,071357.000,V,N*41
$GPGSA,A,1,,,,,,,,,,,,,,*
$GPGV311,0,684,1,4089,,75,9,1,082272*3
$GV321,23,3,9,0,0,261,62,54,,,735*7
$GV331,04,1,2,2,6,33,7
GRC,075.0,,656.03,,20.548,11,.0,201,,*B
$GPG00,,M,1.1,,.9KN*30$GPGGA,071358.000,5656.0013,N,02402.5406,E,0,3,,126.2,M,23.8,M,,*47
$GPGLL,5656.0013,N,02402.5406

I have tested NSS on the following speeds (GPS utility I have on my PC can set GPS module speed only to those fixed speeds)
And look what I found ....
9600 OK
14400 OK
19200 OK
38400 OK
57600 NO!!!
115200 NO!!!

Any ideas ...?

I assume 28800 will work too.

NSS.cpp has this table

#if F_CPU == 16000000

static const DELAY_TABLE PROGMEM table[] = 
{
  //  baud    rxcenter   rxintra    rxstop    tx
  { 115200,   1,         17,        17,       12,    },
  { 57600,    10,        37,        37,       33,    },
  { 38400,    25,        57,        57,       54,    },
  { 31250,    31,        70,        70,       68,    },
  { 28800,    34,        77,        77,       74,    },
  { 19200,    54,        117,       117,      114,   },
  { 14400,    74,        156,       156,      153,   },
  { 9600,     114,       236,       236,      233,   },
  { 4800,     233,       474,       474,      471,   },
  { 2400,     471,       950,       950,      947,   },
  { 1200,     947,       1902,      1902,     1899,  },
  { 300,      3804,      7617,      7617,     7614,  },
};

const int XMIT_START_ADJUSTMENT = 5;
#elif F_CPU == 8000000

static const DELAY_TABLE table[] PROGMEM = 
{
  //  baud    rxcenter    rxintra    rxstop  tx
  { 115200,   1,          5,         5,      3,      },
  { 57600,    1,          15,        15,     13,     },
  { 38400,    2,          25,        26,     23,     },
  { 31250,    7,          32,        33,     29,     },
  { 28800,    11,         35,        35,     32,     },
  { 19200,    20,         55,        55,     52,     },
  { 14400,    30,         75,        75,     72,     },
  { 9600,     50,         114,       114,    112,    },
  { 4800,     110,        233,       233,    230,    },
  { 2400,     229,        472,       472,    469,    },
  { 1200,     467,        948,       948,    945,    },
  { 300,      1895,       3805,      3805,   3802,   },
};

const int XMIT_START_ADJUSTMENT = 4;

If I look at the tables the values of the 8Mhz table is consequently a few % less than half the values of the 16Mhz table, except for the 57600 and 115200 rows, there the rxcenter is just 1 That's an indication there is something noth calculated well, NB in the 16Mhz table there is a factor 10 differencebetween those 2

If you look at double baudrate, the timing halves - a small value {2,3 or 4}

I would try the following values: (guessed based upon the halve of clockspeed and halve baudrate)

{ 57600, 4, 15, 15, 13, },

So what changed is the value to rxcenter - the middle of the bit, the best place to sample the signal -
It was 1 which indicates that the sampling would be more near the edge of the bits, increasing the chance on "too early" sampling

If this works we can scrutinize 115200 too.

Give it a try,

{ 57600, 1, 16, 16, 14 } = working perfectly !!!

Thank you for your time and kind help, robtillaart !!! :wink:

Have you tried other settings that worked @57600 ? e.g { 57600, 1, 17, 17, 14 } ?

Any chance you can fix the 115200 too? you now know how it is done :wink:

Than we can mail Mikal Hart with this info.

Hello robtillaart

You were right - the quest continues ...
My project (cat logger) hosts GPS 0n pins 2,3 and Linksprite JPEG camera on 5,6. Yesterday after making GPS work I tried to snap some pictures to the memory card and despite file names and size are ok, jpg image is not rendered on the PC. I took Duemilanove 328, programmed ASCII example at 57600, connected it to camera input (5,6) at LilyPad. And got complete garbage, nothing even close to what ASCII example should produce. Strange thing is that on GPS output on pins 2,3 still works on 57600, and even GPS module connected to the camera input (5,6) still produces completely sane NMEA sentences recognized by testing utility at my PC.

I will play around with timing trying to make Duemilanove and Lilypad ASCII example work. maybe timing is just barely right for GPS and not enough for Duemilanove ?

So this is a new device (camera) with a similar problem?

Do you have a URL about that camera?
The camera works @57600 ?
Can the camera make snapshots over the hardware serial?
Can you post your code?

Story with the camera is the same as with GPS - it was working perfectly on Duemilanove 328 16Mhz, but the same code is not working on Lilypad 8Mhz.

Slight correction - the camera is set to work in its library on 38400, not 57600. But it changes nothing as baud rate is set in the library, not in the code, burning it in LilyPad had to work right.

NewSoftSerial cameraPort(5,6); //Make sure the camera is plugged into pins 5 and 6 for Rx/Tx
JPEGCamera::JPEGCamera(){
}
void JPEGCamera::begin(void) //Initialize the serial connection
{
	cameraPort.begin(38400);}

So I did another test - connencted Duemilanove with ASCII example (pin 0 and 1)to the
LilyPad pin 5 and 6 with NSS SoftwareSerial example. Set all on 38400. And look what I got -

FYI
Linksprite camera - http://www.sparkfun.com/products/10061
There are examples and library. On with ASCII example I can run that code without modifications and have jpg image on memory card./

Map -> MÁp ascii 97 => ascii 193 difference 96 = 64+32 => bit 5 and 6 are flipped.

Table -> TabÜe => ascii 108 => ascii 219 difference 111 = 64 + 32 + 8 + 4 + 2 + 1

ASCII -> ASC™I => ascii 73 => ascii 153 difference 80 = 64 + 16 => bit 4 and 6

Baudrate is seems OK as most chars come through quite well. There is no pattern in the flipping bits so it looks like the signal gets pulled to HIGH quite often => cabling problem?

TEST: make reading and shake the cables does it get better or worse or no difference?

Seen this remarks?
These only work reliably with a 5V power supply, even though the manual states they can work at 3.3V. If you want to use it at 3.3v, you will need a lower baud rate. Check the comments for more information.

I'm running both Duemilanove and Lilypad from 5V. Memory card uses separate 5 -3.3 V converter, but for this experiment I have disconnected everything from Lilypad and left only three wires between systems - ground, TX and RX.

Shaking cables haven't changed anything. But changing baud rate +1 for 38400 { 38400, 2, 25, 26, 23, } made result almost perfect if not that oddity at the end and cut-ed output (exactly after bin value)

As it is right now

ASCII Table ~ Character Map
!, dec: 33, hex: 21, oct: 41, bin:09 6  : 17b d11x11 081c1,1=1 1

As it should be

ASCII Table ~ Character Map
!, dec: 33, hex: 21, oct: 41, bin: 100001
", dec: 34, hex: 22, oct: 42, bin: 100010

Lilypad

#include <SoftwareSerial.h>
SoftwareSerial mySerial(5, 6);
void setup()  
{Serial.begin(38400);
  mySerial.begin(38400);}

void loop() // run over and over
{if (mySerial.available())
    Serial.print((char)mySerial.read());}

Duemilanove - standart, unmodifyed ASCII example with baudrate set to 38400

Just an idea came in my mind.

The table for the NSS is made for an 8Mhz device. Do you have equipment (scope or other) to see if the lilypad runs on 8M or just a bit slower?