Pages: [1] 2   Go Down
Author Topic: SoftwareSerial for Arduino Due  (Read 4739 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Sr. Member
****
Karma: 9
Posts: 254
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Doesn't this belong in the DUE section?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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 smiley-sad
Is it possible to move it to the DUE section?

Quote
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.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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
Logged

Forum Administrator
Milano, Italy
Offline Offline
Sr. Member
*****
Karma: 22
Posts: 292
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
 _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.
Logged

C.

Smithfield, Rhode Island
Offline Offline
God Member
*****
Karma: 2
Posts: 843
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
 _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...
Logged

Greenville, IL
Offline Offline
Edison Member
*
Karma: 11
Posts: 1309
Warning Novice on board! 0 to 1 chance of errors!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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


Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-razz

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:
Code:
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  smiley

Thanks again,
Luca
Logged

Greenville, IL
Offline Offline
Edison Member
*
Karma: 11
Posts: 1309
Warning Novice on board! 0 to 1 chance of errors!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


 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.

Code:
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:

Code:
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
  }
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Greenville, IL
Offline Offline
Edison Member
*
Karma: 11
Posts: 1309
Warning Novice on board! 0 to 1 chance of errors!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


 I wrote a long reply and accidentally deleted it.   smiley-eek

 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!
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley-cry 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 smiley-mad ....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!!! smiley-roll-blue

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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hardware Serial works  at 10400 baud smiley-grin

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
« Last Edit: January 19, 2013, 05:29:20 am by LucaV72 » Logged

Pages: [1] 2   Go Up
Jump to: