Pages: [1] 2   Go Down
Author Topic: Bug using NewSoftSerial & Servo.h together  (Read 2252 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 77
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,
I spent my whole day trying to get around a bug I got when using the NewSoftSerial library from Arduinana and the Servo Library (Servo.h Version 017) together: One of my two servo motors is going crazy all the time as long as the sensor read by the NewSoftSerial library is connected to the Arduino. One user also reported this problem on the Arduinana website, but there is no fix yet apart from using the previous version of the Servo library (from 016), but there's the writeMicroseconds method missing without my project doesnt work  :-[
Can anybody help me ? I would be very happy about any suggestions  smiley
Logged

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

It might be useful to know which Arduino you have, and what pins you are connecting the servos to, as well as which pins you are using for NewSoftSerial.
Logged

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 77
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am using the Arduino Duemilanove together with the ladyada motor shield, but the problem also exists without it. My sensor, a Parallax MLX90614 is connected to the 5V and two digital Pins. I changed both the sensor and the servo pins, so it's not depending on the pins. I even tried it with the ServoTimer2 library which also has a write(Milliseconds) function, but theres the same problem  :-[

On this page: http://buildsomething.net/Projectblog/?p=37 someone has the same issue.. It obviously has to do something with the interrupts but I don't not what that means..
« Last Edit: December 29, 2009, 06:12:43 am by maxbot » Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all--

I can officially confirm that NewSoftSerial (and really any software serial library) is incompatible with the new Servo library that ships with Arduino 0017.  The problem is that the new Servo library, which is really quite cool, depends on reliable interrupts, where software serial solutions require interrupts to be disabled -- at least for short periods of time.  I discovered this issue when I was trying to upgrade my Reverse Geocache box to 0017, and the only workaround I could come up with was to downgrade the Servo library back to 0016.

I wonder if it would be possible to retain both libraries in 0018?

Mikal
Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 9
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I opened an issue for this: http://code.google.com/p/arduino/issues/detail?id=177.  Not really sure what to do about it.  I don't want to include two Servo library, but maybe we could have this one work differently if you're only using Servo motors on pins 9 and 10?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello all, I am having the same problem described.  Can someone please tell me where I can get the servo 0016 library?  I can't seem to find it anywhere.  Thanks a lot!
Logged

UK
Offline Offline
Faraday Member
**
Karma: 16
Posts: 2883
Gorm deficient
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Can someone please tell me where I can get the servo 0016 library?  I can't seem to find it anywhere
http://arduino.cc/en/Main/Software
« Last Edit: January 14, 2010, 10:27:29 am by GrooveFlotilla » Logged

Per Arduino ad Astra

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

David, I suggest that you put the old servo library as a standalone download for those that have a problem with code such as NewSoftSerial.

Perhaps add a note in the Servo documentation that code such as NewSoftSerial that disables interrupts for relatively long periods of time will not work with the interrupt driven servo library or other libraries that require reliable interrupts.

( a single character at 2400 baud is a very long time from the perspective of a servo pulse)

Mikal, have you tested NSS with the new Tone function in 0018?
Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No, I haven't, mem.  But you're right that there would almost certainly be a conflict.  

I added an end() method in NewSoftSerial 10 (now in beta) that allows for you to turn off a NewSoftSerial interrupt stream.  (Previously, interrupts were enabled forever.)  

Could someone test this with Servo and Tone, i.e. start a NewSoftSerial stream, turn it off with end(), run a Servo, play a Tone, then turn NSS back on with begin(...)?

http://arduiniana.org


Mikal
« Last Edit: January 14, 2010, 12:23:12 pm by mikalhart » Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mikal,

I did a very quick test using tone with 12 servos and a single instance of NSS.

Without nss sending or receiving, the tone frequency and servo pulse widths are within 0.1 % of the expected periods (as measured on a logic analyzer). The mark/space ratio of the tone output very occasionally changes from 50/50 to 66/33 if the start of servo pulse exactly coincides with the end of a tone pulse, but the frequency of the tone does not change.

When NSS is sending data the servo pulse width increase by 50% and the tone period varies by plus minus 100 % (1khz tone sometime is 2khz, sometimes 500hz)

I have not tested receiving using nss or turning NSS off, but when data is not being sent by NSS the tone and servo periods are correct.
The sketch used is as follows.    
Code:
#include <NewSoftSerial.h>

// tone servo test & nss test

#include <Servo.h>

NewSoftSerial mySerial(2, 3);

const int spkrPin = 4;
const int firstServoPin = 5;
const int NBR_SERVOS = 12;

Servo myServos[12];

void setup()
{
  for(int i=0; i < NBR_SERVOS; i++)
    myServos[i].attach(firstServoPin + i);
 
  Serial.begin(57600);
  Serial.println("Goodnight moon!");

  // set the data rate for the NewSoftSerial port
  mySerial.begin(4800);
  mySerial.println("Hello, world?");
  tone(spkrPin, 1000);
}    
    


void loop()
{
  static unsigned long pos = 0;

  if ( Serial.available())
  {
    char ch = Serial.read();
    mySerial.print((char)Serial.read());
  }
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hey maxbot,

have u got your mlx90614 to work with motor even with the 0016?. i'm having huge issue with that still. sensors just stop reading (motor stop too) after motor first loop, here's my code:
Code:
#include <Servo.h>
#include <SoftwareSerial.h>

Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created
SoftwareSerial Temp10(2, 3);

int pos = 0;    // variable to store the servo position
int prev_temp =0;
void setup()
{
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  Serial.begin(115200);
  Temp10.begin(2400);
  delay(100);
  Temp10.print(0,BYTE);
  Temp10.print("!TEMc");
  Temp10.print(0x5A,BYTE);
  Temp10.print(7,BYTE);
  
  pinMode(2,INPUT);
  pinMode(3,INPUT);
}
 
 
void loop()
{
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                // in steps of 1 degree
    prev_temp = Acqu_Temp();
    Serial.print("Temperature= ");
    Serial.print(prev_temp,DEC);
    Serial.println(" Degrees Celsius");
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {                                
//    prev_temp = Acqu_Temp();
//    Serial.print("Temperature= ");
//    Serial.print(prev_temp,DEC);
//    Serial.println(" Degrees Celsius");
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}


int Acqu_Temp()
{
 static char rByte[10];
 char rChar;
 int Temp1, Temp2, Temp3;

   rChar = Temp10.read();
   if (rChar == 'T') {
     rByte[0]=rChar;
     rChar=Temp10.read();
     if(rChar=='E')
     {
         rByte[1]=rChar;
         rChar=Temp10.read();
         if(rChar=='M')
         {
           rByte[2]=rChar;
           rByte[3]=Temp10.read();
           rByte[4]=Temp10.read();
           rByte[5]=Temp10.read();
           Temp1 = rByte[4] + rByte[5]*256;          
           Temp3 = (Temp1/100*2)-273;
         }
     }
   }

 return(Temp3);
}

Thanks
« Last Edit: April 01, 2010, 02:04:39 am by minhtue86 » Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

minhtue86,

I think your problem almost certainly stems from dropped characters from your sensor.  You should migrate to NewSoftSerial or Serial.  SoftwareSerial RX and delay() do not play well together.  Every time you do a delay(15), you are missing whatever important data arrived from your sensor.

Mikal
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Mikal,

Thank you very much for the reply.

I tried to switch to newsoftserial. The motor seems to work now(rotate as intended), but the sensors still seem not work, it wont print out the temperature on the serial command window like i wanted (without servo write command it would work). I even try to control the motor manually by sending pulses (the commented code in the void loop()) but result still the same

Do you have any more idea where I could do things wrong?

Thank you so much

Code:
#include <NewSoftSerial.h>
#include <Servo.h>

NewSoftSerial Temp10(2, 3);

int RESET = 12;
int lastPulse = 0;

Servo myservo;
int pos = 0;

void setup()
{
  pinMode(RESET,OUTPUT);
  digitalWrite(RESET,LOW);
  delay(10);
  pinMode(RESET,INPUT);

  myservo.attach(9);
//  pinMode(9,OUTPUT);
  Temp10.begin(4800);
  Serial.begin(115200);
  delay(100);
  
  Temp10.print(0,BYTE);
  Temp10.print("!TEMc");
  Temp10.print(0x5A,BYTE);
  Temp10.print(7,BYTE);
  delay(1000);
  pinMode(3,INPUT);
  
}
 
void loop()
{
    checkTemp();
    myservo.write(pos);
//    if ((millis() - lastPulse >= 20)) {
//      digitalWrite(9, HIGH);   // start the pulse
//      delayMicroseconds(1000);  // pulse width
//      digitalWrite(9, LOW);    // stop the pulse
//      lastPulse = millis();           // save the time of the last pulse
//    }
}

int checkTemp()
{
  static char rByte[10] ;
  char rChar;
  static int Read = 0;
  static int rcount=0;
  int Temp1;
  int Temp2;
  int Temp3;
  while (Temp10.available() > 0) {
    rChar = Temp10.read();
    if (rChar == 'T') {
      Read = 1;
      rcount = 0;
    }
    if (Read == 1) {
      rByte[rcount] = rChar;
      rcount++;
    }
  }
  
  if (rcount >= 6) {
    if ((rByte[0] == 'T') && (rByte[1] == 'E') && (rByte[2] == 'M')) {
      Temp1 = rByte[4] + rByte[5]*256;
      Temp2 = (Temp1/100);
      if (Temp1*2 < 27315) {
        Temp3 = ((27315-(Temp1*2))/100);
      }
      else
      {
        Temp3 = (Temp1/100*2)-273;
      }
       Serial.print("Temperature= ");
       Serial.print(Temp3,DEC);
       Serial.println(" Degrees Celsius");
      
      rcount = 0;
      Read = 0;
    }
  }
}
Logged

Holland
Offline Offline
Sr. Member
****
Karma: 0
Posts: 439
Arduino likes cookies too
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try putting a delayMicroseconds(1) after the read from the NewSoftSerial, that solved the issue for me.
Logged

Bedum. grunn, The netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i have the same problem but none of the tips above helped
i.e servo library 16

any other tips?
Logged

Pages: [1] 2   Go Up
Jump to: