SoftwareSerial for Arduino Due

Hi, I am trying to port an automotive project I have been working on for a while (on Mega 2560 board) to my brand new Arduino Due board. Problem is that SoftwareSerial library is missing. I need it to sync with OBD 10400 baud since standard Serial is not accurate enough at this speed. I modified the original library to work at 10400 baud and it connected flawlessy. Unfortunately my version does not compile under Due board and no other version is available. Is there any port under way, of the library?

Thanks in advance, Luca

Not sure what you mean by "missing", I don't think there are any problems using the Due with SoftSerial, can you post your code?

Doesn't this belong in the DUE section?

Doesn't this belong in the DUE section?

You are right, this is my first post and I posted it in the wrong place, sorry :( Is it possible to move it to the DUE section?

I don't think there are any problems using the Due with SoftSerial

The Software serial library is not present in the DUE tree. I tried to copy it to the libray folder but it won't compile (it links avr libs). And the reason was obvius once I looked inside: SoftwareSerial is tuned only for 8,16,20 MHZ (DUE is 84 MHz) and makes some use of inline assembly . Moreover DUE has (I think) a different approach to change interrupts. But I could be wrong, I have been using the 1.5.1 IDE only for two days.

The DUE has 4 hardware serial port, doesn't it? Why are you needing software serial ports?

The DUE has 4 hardware serial port, doesn't it? Why are you needing software serial ports?

Because I am developing an automotive project which needs 10400 baud on the serial port. With Atmega328P and Mega2560 I tried to set the hardware serial port to 10400 but I could not connect to the ECU of the car. So I modified the SerialSoftware library in order to accept this connection speed and it worked like a charm. I have been testing the system for more than 6 months and it almost never dropped a frame. Now I fear to have the same problem on the new DUE so I would be very happy to have a SoftwareSerial library to modifiy to 10400 baud. Luca

The Serial class uses the following formula to obtain the clock divider:

  _pUsart->US_BRGR = (SystemCoreClock / dwBaudRate) / 16 ;

in your case the perfect divisor would be 84000000 / 10400 / 16 = 504.8076
but the register will truncate to the integer 504.
The error is under <0.2%

IMHO you should give a try with Serial.

cmaglie:
The Serial class uses the following formula to obtain the clock divider:

  _pUsart->US_BRGR = (SystemCoreClock / dwBaudRate) / 16 ;

in your case the perfect divisor would be 84000000 / 10400 / 16 = 504.8076
but the register will truncate to the integer 504.
The error is under <0.2%

IMHO you should give a try with Serial.

I agree with this assessment. Failing that, perhaps the Multi Serial shield would work…

Post your OBD2 initiation part of your code and maybe we can help adjust it to work with hardware serial.

Thanks to you all for your answers.

I think I will try again Hardware Serial. First time I tried it was with Atmega328p and it failed. Then when I upgraded to Mega2560 I did not try again because the software was very stable then. But since I have to rewrite half of the program (LCD panel is going to be replaced by a 5" TFT display so the whole HMI must be rewritten) there is space for many tests :stuck_out_tongue:

However here is the software (for Atmega2560):
http://luca72.xoom.it/td5mapsuiteweb/archive/td5opencom/td5opencom11q.zip

OBD2 communication management is in file td5comm.cpp, this is the read/write part:

boolean Td5Comm::read_byte(byte * b)
{
  int readData;
  boolean success = true;
  byte t=0;

  //digitalWrite(ledPin, HIGH);
  while(t != READ_ATTEMPTS  && (readData=obdSerial.read())==-1) 
  {
    delay(1);
    t++;
  }
  //digitalWrite(ledPin, LOW);

  if (t >= READ_ATTEMPTS) 
  {
    success = false;
  }

  if (success)
  {
    *b = (byte) readData;
  }

  return success;
}

void Td5Comm::write_byte(byte b)
{
  //digitalWrite(ledPin, HIGH);
  obdSerial.write(b);
  delay(Td5RequestByteDelay);  // ISO requires 5-20 ms delay between bytes.
  //digitalWrite(ledPin, LOW);
}

If somebody can give me some suggestions they are very welcomed :slight_smile:

Thanks again,
Luca

You have a function that starts the communication process. I am showing the first part of it only as it is fairly long. I am assuming there is something in your code that help you get from case “1” and past the blank case “2” to continue to case “3” and so forth.

void Td5Comm::initComm()
{
  unsigned long currentTime = millis();
  
  switch (initStep)
  {
  case 0:
    // setup
    ecuConnection = false;
    initTime = currentTime + 300;
    initStep++;
    break;
  case 1:
    if (currentTime >= initTime)
    {
      // drive K line high for 300ms
      digitalWrite(K_OUT, HIGH);
      digitalWrite(ledPin, HIGH);
      initTime = currentTime + 300;
      initStep++;
    }
    break;
  case 2:
  case 3:
    if (currentTime >= initTime)
    {
      // start or stop bit
      digitalWrite(K_OUT, (initStep == 2 ? LOW : HIGH));
      digitalWrite(ledPin, (initStep == 2 ? LOW : HIGH));
      initTime = currentTime + (initStep == 2 ? 25 : 25);
      initStep++;
    }
    break;
  case 4:
    if (currentTime >= initTime)
    {
      // switch now to 10400 bauds
      obdSerial.begin(10400);

      // bit banging done, now verify connection at 10400 baud
      if (getPid(&pidInitFrame) <= 0)
      {
        digitalWrite(ledPin, LOW);
        initStep = 0;
        break;
      }

      lastReceivedPidTime = currentTime;
      initTime = currentTime + Td5RequestDelay;
      initStep++;       
    }

I have a code that works for me for my initialization, it is not as elegant as yours but, it works for my situation. I am using a 1284 chip that has two hardware serial ports. Maybe you can adapt the code for your application. Here it is:

 digitalWrite (TX, HIGH); // makes K-line high pin 3
  digitalWrite(ledPin,HIGH);
  delay(2000);       // wait for K-line to be clear pin3
  digitalWrite (TX, LOW); // makes K-line low  pin3
  delay(25);
  digitalWrite (TX, HIGH); // makes K-line high  pin3
  delay(25);        //last delay before first message
  Serial1.begin(10400);
  //send package first message
  for (int i = 0; i < 5; i++){
    Serial1.write(message[i]);
    byte inByte = Serial1.read();
    delay(1);                 //inter byte delay for to match k-line spec. changed from 15ms to 1
  }

Hi, thank for sharing your experience. Before using a special version of SoftwareSerial (modified by me) tuned for 10400 baud, I tried for a while the Hardware Serial with no success. My initial code was similar to yours. It worked, but the problem was on long frames. It was reliable up until the first three or four bytes then it went out of sync starting loosing bits. At the beginning I used Atmega328p and the only solution I found was adapting the SoftwareSerial library. After few months I run out of RAM so I upgraded the controller to Atmega2560 but I did not try to go back to Hardware Serial (at that point communication was already very reliable). Maybe, as in your case, it worked with the Mega board. Now I am going to try it first on Atmega2560 then, if it works, I will try it on DUE.

In my code (I borrowed it from OBDuino project) states 2 and 3 share the same code, 25 ms LOW and 25ms HIGH.

Luca

I wrote a long reply and accidentally deleted it. :astonished:

To summarize, if you want to pursue using hardware serial, you need to strip your code to the basics, and make sure that your problem is the Serial method and not something in your sketch causing the problem.

I suspect that your button checking, and LCD printing, may be causing the serial to lag behind or have a buffer problem. Stripping your code to the basics and printing the OBD2 output to the serial monitor will help you troubleshoot the problem. Once the problem is found, you can optimize the other functions to work with your code.

P.S. When I first started my project, I printed what mode I was in. I called the modes 1,2,3,4. For instance mode 1 = initialization. Using this method, I was able to determine how far my sketch went before problems arrived. I also printed my OBD2 messages to help me look for errors.

Keep working at your sketch, it looks like it has a lot of nice features so far!

At the very beginning the code was stripped to almost nothing, but on Atmega328p there was no way to receive long frames. Then I made some researches on the web and I found many people having the same problem at 10400 baud (how OBDuino works is a mistery to me...) so I switched to Software serial and everything worked OK. I never tried to do the same thing on Mega2560 (which is very similar to your 1280). Now I have three devices running with SoftwareSerial: the ECU emulator, a basic device with Atmega328p and LCD 20x4 and a full diagnostic device (see video below) running on Atmega2560. Yesterday I tried a very basic circuit and SW with Arduino DUE and MC33290 but I do not know how I got two chip (MC33290) burned =( This is very strange because I tested them both on the ECU emulator prior to connect them to DUE and they worked. Once connected to TX/RX on the DUE they got burned :0 ....really strange (and SAD, since they are not very common and now I have only one left). Never happened before during the hundreds of test I did to have the project running....

I really have to learn many things about this DUE board!!! :roll_eyes:

Anyway here is the device (with Mega2560) running on my Land Rover Defender: http://luca72.xoom.it/td5mapsuiteweb/archive/td5opencom/td5oc_running.wmv

This video was taken last Summer and many functions were missing, now it is quite complete and it is able to save a log fuelling data on the SD card while running, reset errors, read settings and so on.

Next step is to upgrade to Arduino DUE and 5" TFT touch display. It seems it will not be as easy as I though..... Luca

Hardware Serial works at 10400 baud :D

I cannot explain the two chips burned but I should have done something wrong on the breadboard... probably my fault (I ordered five more MC33290 to be sure!!!).

I had to make some minor changes to my code, but eventually communication was stable with DUE. No frames lost even under continuous writing/reading (I tested instrument mode, it exchanges a frame every 250 ms).

Thanks to everybody for your suggestions!!!

Luca

Excellent work! Nice video!

(I ordered five more MC33290

I have 2 MC33290 chips but, I have discovered that it is simply a voltage level converter. Therefore, I am using a LM393 DIP chip to convert my 12volt K-line to 5volt for my Arduino. Basically the LM393 is set-up as a dual comparator, one comparator is the TX from the Arduino with it's collector tied to 12v, and the other comparator is from the K-line of the bike with it's collector tied to 5v. I could e-mail a schematic to you if you need it. I have a few extra circuit boards for the LM393 level converter that I have made work for my Arduino.

I really like your project. My project is still early in development currently, I have a Bobuino board with RTC and SD card, a 2x16 LCD screen shield with buttons and my level converter circuit is a separate board. I hope to have a touch screen for a user interface then, have all other electronics hidden. In my case the Arduino will be in the back of my motorcycle and the screen will be mounted somewhere at the front of the bike.

I have one request if you don't mind, could you list your pin-out that goes with your code? When I say pin-out I mean: LCD pins- 9,8,7,6,5,4 etc. , SD card pins 10,11,12,13, button pins....... etc. It is OK if you want to keep some of your build secret, you have done a lot of good work.

Thanks for the appreciations. And yes, I would really like to see the schematics for LM393!!!
Do not worry to ask for the code, I have already stolen something from the your code (the one you posted) and tested this evening with success XD

About the pinout I posted the full code some posts behind. Following you can find the link:
http://luca72.xoom.it/td5mapsuiteweb/archive/td5opencom/td5opencom11q.zip

Download it and open the file named Td5Defs.h, it contains all the pinout for Atmega328p and for Mega2560.
Anyway here is a brief summary:

#if  defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
  #define LCD_D7                2
  #define LCD_D6                3
  #define LCD_D5                4
  #define LCD_D4                5
  #define lcdBKlightPin         6
  #define LCD_RS                7
  #define LCD_EN                8
  #define ledPin                9
  #define SD_CS                10
  #define MOSI                 11
  #define MISO                 12
  #define SCK                  13
  #define keyPadPowerPin       A0
  #define keyPadButtonsPin     A1
  #define K_OUT                A2  
  #define K_IN                 A3
  #define SDA                  A4
  #define SCL                  A5
#endif

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  #define LCD_D7               40
  #define LCD_D6               38
  #define LCD_D5               36
  #define LCD_D4               34
  #define lcdBKlightPin         2
  #define btEnablePin           7
  #define LCD_RS               22
  #define LCD_EN               24
  #define ledPin               13
  #define SD_CS                53
  #define MOSI                 51
  #define MISO                 50
  #define SCK                  52
  #define keyPadPowerPin        3
  #define keyPadButtonsPin     A1
  #define K_OUT               A15
  #define K_IN                A14
  #define SDA                  20
  #define SCL                  21
#endif

Everything is OpenSource - OpenHardware so I am very pleased to share. There is only a little part I cannot share publicly: the seed-key table (residing in an external EEPROM) since it is reverse engineered and I fear to be break some law. Here you can find the rest of the project (non Arduino related): http://luca72.xoom.it/td5mapsuiteweb/index.html
There is some Android code too (still in very early stage and not published yet), since it connects to my 8" tablet via bluetooth and uses it as a second monitor (LCD is primary.

If you are interest you can contact me via e-mail, it is on my website.

So you are going to use your project on the motorbike? Really interesting, since I am a biker too!!! BTW I really need a RTC. Which one do you use? Is it compatible with DUE levels or do you use a translator?

Luca

The Arduino board I am using is made by CrossRoads from this forum. It has built in RTC and SDcard slot. A picture of it is on this page http://www.crossroadsfencing.com/BobuinoRev17/

And yes, I would really like to see the schematics for LM393!!!

I can not figure out how to make a picture of the schematic but, I will send you an Eagle .sch file of level converter. Please double check the design, it is board that I am designing but, it is not finished...........e-mail is sent.

Do not worry to ask for the code, I have already stolen something from the your code (the one you posted) and tested this evening with success

I am glad to hear that the code worked for you.

So you are going to use your project on the motorbike?

I have a 08 Suzuki GSXR and I have been communicating with it using a computer and program written by some other people http://ecuhacking.activeboard.com/. My project replaces the computer with my Arduino to log data and display sensor data. I have a lot of the code working but, there are still bugs that need worked out.

I can tell you many things about the bike programming but, it would have to be another thread.

LucaV72 wrote: I have 2 MC33290 chips but, I have discovered that it is simply a voltage level converter. Therefore, I am using a LM393 DIP chip to convert my 12volt K-line to 5volt for my Arduino. Basically the LM393 is set-up as a dual comparator, one comparator is the TX from the Arduino with it's collector tied to 12v, and the other comparator is from the K-line of the bike with it's collector tied to 5v.

Have you mentioned that the DUE I/O-Pins are specified for 3.3 Volt only, 5 Volt would damage the chip. Best regards Gerd

Have you mentioned that the DUE I/O-Pins are specified for 3.3 Volt only, 5 Volt would damage the chip.

I was speaking of my application using a 1284P chip. My converter could also work with 3.3volt when connected to a 3.3volt of Due.