Go Down

Topic: Hardware Serial RX doesn't work with Mini Pro 328 3.3V (Read 1 time) previous topic - next topic

trementina

Apr 29, 2011, 01:07 am Last Edit: Apr 29, 2011, 11:15 pm by trementina Reason: 1
Hardware Serial RX doesn't work with Mini Pro 328 3.3V.
(The TX line seems to work fine)

Serial.available() return 0.
Serial.read() return garbage.

Is this a known bug? Any chance it wil be fixed?

Thanks

[EDIT, i have done more debugging, and these are my conclusions :
1. i have done a mistake during debugging : byte f = Serial.read() is a BUG, you must use int f = Serial.read()
2. using 115200 baud generate many errors during reading : i have tried 57600 and it's better
3. Serial.available() always return 0 (on mini pro 3.3)

Well, i will not use Serial.available(), and slow down UART Speed.

nickgammon

Well now. Let's see your circuit. The sketch on the sending whatever-it-is. The sketch on the receiving device.

My immediate reaction is that if Serial.available() returns 0, then there is no point in doing Serial.read because you are reading "no data".

Before we start talking about fixing bugs, let's eliminate user error.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

trementina

#2
Apr 29, 2011, 04:19 pm Last Edit: Apr 29, 2011, 05:17 pm by trementina Reason: 1
Hello Sir,
thanks for answer.

I agree with you that most the time it's user error (my error).
I only asked if there was some bug in the library for the 3.3v version of Mini Pro.

Anyway, this is my project:



My project is "StarFinder" : finding stars with Stellarium on Maemo5/NOKIA900 and a Green Laser
In this image you can see Stellarium on Nokia900, modded and recompiled to talk with arduino.

The wireless communication is done with Bluesmirf Silver.

To find the Stars ia use an AHRS 9DOF, implemented with with the sparkfun breakout board (75 Euros!) and
the GREAT Sebastian O.H. Madgwick code.

The feedback is done with a great ULCD144 GOLDELOX lcd screen. Only for debugging i use a cheap Nokia 5110.
I had problems sharing the uart between the Sensor and the ULCD144 (i tried a multiplexer, but didn't like it).
So  i have bought a sparkfun SPI<->UART to talk to the lcd.

You can also see the OLS Sniffer, i have used to sniff the TX, RX lines



In this second image you can see the garbage i read on RX, displayed on the Debugging LCD.





In this fourth image you can see the INCREDIBLE ULCD144! It cost about 30 Euros, and it's really great!



In this fifth image you can see the sniff of the TX line. When i push the button for 3 seconds, StarFinder start "calibration mode", and send the bytes "MOON   " to Stellarium on Nokia900. Stellarium search the position of the Moon, or some other Visible Star : Sirius, Polaris, Vega, etc... and send the Triple (Name 10 bytes, yaw 2 bytes, pitch 2 byte) = total 14 bytes to Arduino.



In this last image you can see the sniff of the RX line : the answer from Stellarium/Nokia900 to StarFinder/Arduino. The stream of bytes "seem" good : "Polaris   YYPP" (YY = two bytes for yaw MSB, PP = two bytes for pitch MSB). The Moon was not visible, and Stellarium looked for Polaris Star.



...Oh! The Laser... here it is, modded and ready for a PCB.

And this is some code from the sketch. The problem is inside the method "moonFound". The commented code use the method Serial.available(), but it return 0 (displayed on the debugging LCD). The debugging code read one byte at time, when it's available, and "return true" to the caller only when 14 bytes has been collected (name, yaw, pitch)

The UART, Nokia, BT etc... all works at 115200 baud

Code: [Select]

// "finder" is the App Object
void setup() { finder.init(9/*button*/, 8/*lcd_ok*/, 10/*spi_select*/); }
void loop() { finder.update(); }

class StarFinder
{

 inline void init(byte pin_button, byte lcd_avail, byte spi_select)
 {
   int i;
   Serial.begin(115200);
   [...]
 }

 [...]

 inline void update()
 {
   update_ahrs();
   button.update(s);
         
   switch (stato)
   {
     case Compass:
     {
       [...]
       
       if (button.pushed(s)) stato = Moon_Calibrate;
       
       [...]
       break;
     }
     
     [...]
     
     case Moon_Calibrate:
     {
       stellarium.searchMoon();
       last_millis_stellarium_calibrate = millis();
       stato = Moon_Calibrate_Wait_Answer;
       break;
     }
     
     case Moon_Calibrate_Wait_Answer:
     {
       if (millis() - last_millis_stellarium_calibrate > 3000)
       {
         stato = No_Answer_from_Stellarium;
         break;
       }
       if (stellarium.moonFound(yaw_moon_real, pitch_moon_real, moon_name))
         stato = Moon_Calibrate_Ask_Clik;
         
       break;
     }
 
    [...]
} // end class StarFinder

class NOKIA900 // That is "stellarium" object
{
  [...]
 inline bool moonFound(int& yawm, int& pitchm, char* name)
 {
   //*** Start of debugging code
   static int lbuf = 0;
   static char buf[14];
   
   byte f = Serial.read();
   if (f == -1) return false;
   buf[lbuf++] = f;
   if (lbuf < calibration_length) return false;
   lbuf = 0;
   
   strncpy(name, buf, 10);
   yawm = ( (buf[10]<<8) & 0xFF00 );
   yawm = yawm | ( buf[11] & 0x00FF );
   pitchm = ( (buf[12]<<8) & 0xFF00 );
   pitchm = pitchm | ( buf[13] & 0x00FF );
   
   lcd.clean();
   lcd.prints("Hello");
   lcd.prints(name,2);
   char t[10];
   
   return true;
   //*** End of debuging code
   
   //*** Start of preferred code
   int n = Serial.available();
   if (n < calibration_length) return false;  
   if (n > calibration_length)
   {
     Serial.flush();
     return false;
   }
   
   for (int i=0; i<10; ++i)
     name[i] = Serial.read();
   
   byte c = Serial.read();
   yawm = ( (c<<8) & 0xFF00 );
   c = Serial.read();
   yawm = yawm | ( c & 0x00FF );

   c = Serial.read();
   pitchm = ( (c<<8) & 0xFF00 );
   c = Serial.read();
   pitchm = pitchm | ( c & 0x00FF );
   
   return true;  
   //*** end of preferred code  
 }

  [...]
}

nickgammon

It's an impressive-looking project. I was thinking of getting a telescope that is computer-controlled and you seem to have gone a long way down that path.

I can't comment on the library per se, but I am a bit doubtful of the code snippets you have shown. To really comment I need to see the lot, as the excerpted stuff hides a lot of relevant detail. For example, what is calibration_length?

I'm a bit concerned about this:

Code: [Select]
//*** Start of preferred code
    int n = Serial.available();
    if (n < calibration_length) return false; 
    if (n > calibration_length)
    {
      Serial.flush();
      return false;
    }


First, how do you know Serial.available() returns zero? And of course it will for a while until the data arrives.

Then you are checking for an exact number of bytes (calibration_length whatever that is). If you get a single extra one (eg. a newline character) then you throw the whole lot away. That could account for appearing to get nothing. And at that speed of transmission the extra byte might arrive quite fast. It would be better, I think, to wait for calibration_length bytes, process them all, and then, if you must, flush away any extra ones.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

trementina

#4
Apr 29, 2011, 11:42 pm Last Edit: Apr 29, 2011, 11:48 pm by trementina Reason: 1
Dear friend,
thank again for interest.

I have solved my problem, but have edited my first post.
I have done more debugging, using the Serial port of the PC, an RS232/TTL Adapter, the sniffer etc etc...

I did a stupid error in the debugging code (not in the orginal code): i wrote char f = Serial.read(), but of course
i must write int f = Serial.read(), to test for available data.

Then i have seen  many errors reading at 115200 baud : i have reduced the baud rate to 57600 in the sketch, the BlueSmirf, and the Nokia, and it's realy better.

During the tests, i have always invoked Serial.available() (before Serial.read() of course), but it has always returned 0 (displayed to the Nokia 5110 debugging LCD, and to sscom32 serial program under Windows XP)

Now i don't use Serial.avilable(), my modified code is working fine :
Code: [Select]

   int f = Serial.read();
   // if no data available, do nothing, and go on updating the DCM filter in the mail loop
   if (f == -1) return false;

   // if there is some data, i read only 1 char (it's not important trying to read immediately all the data available)
   buf[lbuf++] = (char)f;

   // if i have NOT collected the whole packet, do nothing and go on updating the DCM filter in the mail loop
   // (  FIXED packet size from Nokia! This is the answer to the instruction    [...] if (n > calibration_length)  ... [...]
   //     i can't accept more characters than expected, there was some problem. )
   if (lbuf < calibration_length) return false;

   // if have collectet the whole packet from Nokia, finally answer to the caller to go to next STATUS
   lbuf = 0;
   
   strncpy(name, (char*)buf, 10);
   yawm = ( (buf[10]<<8) & 0xFF00 );
   yawm = yawm | ( buf[11] & 0x00FF );
   pitchm = ( (buf[12]<<8) & 0xFF00 );
   pitchm = pitchm | ( buf[13] & 0x00FF );
   
   return true;


If you want to buy a telescope, maybe Stellarium could be a good choice for you. It is an Open Source, and i know it has plugins to CONTROL telescopes! The bad news is that is has been recompiled only under Nokia900 (for Mobile), and not under Android, and Nokia900 is NOT cheap! (I have bought my Nokia900 on eBay for 300 Euros)


Go Up