Pages: 1 2 [3]   Go Down
Author Topic: Serial Communication  (Read 2497 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The reason is for the output of an understanding of one value from the incoming bytes. I understand that functions in a float structure can be used but I could not get a code to run perfoming this conversion to produce a value of -1g for example.

I will do that. I was not sure how you posted code-i checked off the box near the bottom of the posting but I never got a popup box to do so. I understand now

Thank you
Logged

UK, Southwest
Offline Offline
Full Member
***
Karma: 5
Posts: 138
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Blackdragon,
You do not need to get bogged down in the maths of the floating point number.  My code example shows how to change the 4 bytes received to a float.  Its very similar to the example from the website, which you also found.  The technique is to put the 4 received bytes at the same addresses as the float variable, then ask the computer to interpret the float value.  The arduino already 'knows' that if it is given a float, how to manipulate it.  You don't have to know.

look at this code, from your example:
Code:
for (i=1; i<5; i++) {
incomingByte = (float)Serial.read();

i = 1.
Serial.read() returns a byte - 8 bits, say 00101001.  That example is hex2A, or decimal 42 (32 + 10).   If you cast that to a float - the (float) operation - you get a floating number with a value of 42.0  It is represented as 4 bytes, and using the www.h-schmidt.net/FloatApplet/IEEE754.html website, the values are probably 42280000.
That number, 42.0 is assigned to incomingByte overwriting any previous value of incomingByte.
i = 2.
Serial.read() returns a byte - 8 bits, say 00000001.    If you cast that to a float - the (float) operation - you get a floating number with a value of 1.0  It is represented as 4 bytes, and you can work out what they are but it doesn't matter.  That number, 1.0 is assigned to incomingByte - IT DOES NOT ADD TO IT.
i=3
much the same
i=4
much the same
i=5
exits loop
 
It will end up with the (floating) value of the last of the 4 bytes read.

You need to write the 4 bytes into a byte array and then use those 4 bytes as a float, as per my code.  A cast - which is what the (float) operation is called - will not work.  The sketch I wrote a few nights back tries to do that.

Please also answer the question of how the device is connected, because I am interested in how the single serial input pin is used for the device but the serial out goes both to the computer AND the device.  That is not a way of connecting hardware that I have met before.

The reason I tried to write the last sketch with a loop, is that you can  shake the device up and down, and see if the values are changing.  With a one shot, its going to be difficult to alter the acceleration at the exact time you want the reading.  At least for testing, try using a loop to read the values repeatedly.  Then convert to your one-shot code.
Logged

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

I was just confused since I received 4 zeros in the output since I was expecting one final value. Would you say the last code posted with your code incorporated was done correctly? I think I am getting the float part but was just not sure with what I was receiving. Is there a way to extend the decimals to more than 2 places to see if the data is 0.005 for example?

The setup is through the usage of pins 0-1 on the Duemilanove. Using the USB cable to upload the coding to the board, then once the code is running, the command byte is transmitted on pin 1 and received on pin 0. To my understanding of the board, the transmission pin works in correspondance to the USB cable to print the information on the computer screen to validate the data.

Thank you
Logged

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

Well I am finished now. I was successfully able to get the unit to convert the byte to a float value which I can confirm and makes sense.

Thank you all so very much for progress and promptness the whole way through. Our project isn't fully complete but this portion is ready for integration in my perspective.

Thank you again. Especially Shelleycat for all your coding (I dont have any idea how long those took to write up) but it all really helped me progress and learn what I needed to do along the way.
Logged

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

One last concern is since we have an Arduino Duemilanove which contains a USB port, can we print the serial data (currently written to a computer screen via usb) to a a USB thumb drive through a USB type A to type B cable. Are there certain write functions that are needed or must you use a ftdi viniculum chip?

thanks
Logged

UK, Southwest
Offline Offline
Full Member
***
Karma: 5
Posts: 138
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm glad it worked.

As far as I know the arduino cannot drive a USB as a master, so it will not be able to write to a thumb drive.  On the forums there are numerous posts about writing to a SD card, and there is a library for that.  I've not tried it.

What I have done with an arduino as a data logger is use hyperterminal on the computer to receive the data from the arduino, and capture that to a file.

As for printing the float with 3 decimal places, this might work:
Code:
// prints a float with 3 decimal places
void print_float(float f)
{
  long intpart = (long) f; // get the integer part of number
  long frac 1000.0 * (f - float(intpart));
  Serial.print(intpart);
  Serial.print('.');
  Serial.print(frac);
}
Logged

0
Offline Offline
Faraday Member
**
Karma: 8
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
he arduino cannot drive a USB as a master
Correct.

Quote
so it will not be able to write to a thumb drive
It can't directly, but it can with the help of a chip known as the Vinculum VNC1L.  There are modules (VDIP1, VDIP2, VMUSIC, etc) that have been interfaced to the arduino with varying degrees of success.

It's not trivial or trouble free, but it is doable.  Search the forum and maybe the playground for discussions.

-j

Logged

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

For memory we are planning to use the Spark Fun Logomatic V2 SD logger. This will work correct?

The other issue of concern is that I integrated my code with my coding for servos and they seem to glitch even with all the print statements removed but the command byte one (d). I tried to switch the transmit and receive off of serial (0,1) and use another digital set on the Duemilanove (6,7) but I have had no luck. Any suggestions as to where I am going wrong? It compiles but I dont receive relevant data. Thanks

[#include <NewSoftSerial.h>

int RXpin = 6;
int TXpin = 7;

NewSoftSerial IMU = NewSoftSerial(RXpin,TXpin);


typedef unsigned char byte;

byte incomingByte = 0;     // for incoming serial data
byte incomingByte1 = 0;     // for incoming serial data
byte incomingByte2 = 0;     // for incoming serial data
byte incomingByte3 = 0;     // for incoming serial data
byte incomingByte4 = 0;     // for incoming serial data
int EulerX = 0;
int EulerY = 0;
int EulerZ = 0;

int i;
int t = 0;

int servo1 = 4;
int servo2 = 2;
int pulseWidth1;
int pulseWidth2;

void servoPulse1 (int servo1, int EulerX) {
  pulseWidth1 = ((EulerX * 10.9) + 1500);  // Converts angle to microseconds
  digitalWrite(servo1, HIGH);           // Set servo high (turns it on)
  delayMicroseconds(pulseWidth1);       // Wait a very very small amount
  digitalWrite(servo1, LOW);            // Set servo low (turns it off)
  //delay(20);                            // Typical Refresh cycle of servo (20 ms)
  //Serial.println (pulseWidth1, DEC);
 
}

void servoPulse2 (int servo2, int EulerY) {
  pulseWidth2 = ((EulerY * 10.9) + 1500);  // Converts angle to microseconds
  digitalWrite(servo2, HIGH);           // Set servo high (turns it on)
  delayMicroseconds(pulseWidth2);       // Wait a very very small amount
  digitalWrite(servo2, LOW);            // Set servo low (turns it off)
  //delay(20);  // Typical Refresh cycle of servo (20 ms)
  //Serial.println (pulseWidth2, DEC);
}

float Convert754(byte bits25_32, byte bits17_24, byte bits9_16, byte bits1_8);
char d;

float Convert754(byte bits25_32, byte bits17_24, byte bits9_16, byte bits1_8)
{
    unsigned char bytes[4];
    float floatval;
 
    bytes[3] = bits25_32;
    bytes[2] = bits17_24;
    bytes[1] = bits9_16;
    bytes[0] = bits1_8;
 
    floatval = *(float*)bytes;
 
    return floatval;
}

void setup()
{
  pinMode(servo1, OUTPUT);
  pinMode(servo2, OUTPUT);
  pinMode(6, INPUT);
  pinMode(7, OUTPUT);
  // set the data rate for the SoftwareSerial port
  }            
                  
void loop() {
  Serial.begin(115200);
IMU.begin(115200);
delay (10);

d = 206;               // DEC for 0xCE (Euler Angle)     change for desired output see Microstrain Protocal
IMU.print(d);
Serial.println (d, DEC);

delay(810);
            
                  
                   if (IMU.available() >= 0){
                       for (i=0; i<1; i++) {// read the incoming byte:
                       incomingByte = IMU.read();

                       Serial.print("\n\nHeader: ");
                       Serial.println(incomingByte, DEC);
                       }    
                       Serial.print("\n");
                        
                       for (i=1; i<5; i++) {
                           if (i==1) { incomingByte1 = IMU.read(); }
                           if (i==2) { incomingByte2 = IMU.read(); }
                           if (i==3) { incomingByte3 = IMU.read(); }
                           if (i==4) { incomingByte4 = IMU.read(); }  
                       }
                       Serial.print("Euler Angle About X: ");
                       EulerX = (float)( Convert754(incomingByte1, incomingByte2, incomingByte3, incomingByte4)*180/3.14);
                       Serial.print(EulerX, DEC);
                       Serial.print("\n");
                      
                       for (i=5; i<9; i++) {
                           if (i==5) { incomingByte1 = IMU.read(); }
                           if (i==6) { incomingByte2 = IMU.read(); }
                           if (i==7) { incomingByte3 = IMU.read(); }
                           if (i==8) { incomingByte4 = IMU.read(); }  
                       }
                       Serial.print("Euler Angle About Y: ");
                       EulerY = (float)( Convert754(incomingByte1, incomingByte2, incomingByte3, incomingByte4)*180/3.14);                      
                       Serial.print(EulerY, DEC);
                       Serial.print("\n");
                      
                       for (i=9; i<13; i++) {
                           if (i==9) { incomingByte1 = IMU.read(); }
                           if (i==10) { incomingByte2 = IMU.read(); }
                           if (i==11) { incomingByte3 = IMU.read(); }
                           if (i==12) { incomingByte4 = IMU.read(); }
                       }  
                       Serial.print("Euler Angle About Z: ");                      
                       EulerZ = (float)( Convert754(incomingByte1, incomingByte2, incomingByte3, incomingByte4)*180/3.14);                      
                       Serial.print(EulerZ, DEC);
                       Serial.print("\n");
                      IMU.flush();
                  }
                  delay (10);
                      
                       servoPulse1(servo1, EulerX);
                      
                      
                       servoPulse2(servo2, EulerY);                      
                  
        

    

}              
][/code]
Logged

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

Well we got the Sparkfun Logomatic to connect and provide feedback to the board on the serial pins. But now the InertiaLink and Logomatic run off the same two pins. Is it possible to move the Logomatic to two other digital pins--such as a void loop with a digital output for the data to be sent to the Logomatic?

Thank you
Logged

Pages: 1 2 [3]   Go Up
Jump to: