0

Logger Shield and Negative Numbers
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Logger Shield and Negative Numbers

by Volkemon on Sun Jun 13, 2010 6:42 pm

Well, the logger project has been going well, with all the holdups one would expect, and a few that were unexpected!

This falls under the latter. I have been sucessfully logging the data from a remote XBee with 4 TMP36 sensors. Goes on the card, and is in a format that is easy to export to Excel.

I added another XBee remote, and only had 1 TMP36 to attach to it. (Gotta order more!) So I grounded the other 3 inputs, and the serial monitor displayed -57* for these inputs. As expected. However, on reviewing the data on the SD card, I was surprised to find the number 4,294,967,239 instead of -57!

Image

This is a snippet of code that produces the numbers:

Code: Select all | TOGGLE FULL SIZE
        int analogChannelData2 = (packet[13] <<8) | packet[14];  // reads byte 14, shifts it over 8 bits, and appends byte 15 to it to form the raw data variable from the A/D converter reading
        Serial.print(analogChannelData2);Serial.println(" TMP36 2 reading ");Serial.println("");  // prints raw A/D readingfor debugging
        Serial.print(packet[13], HEX);Serial.print(" byte 14  ");Serial.print(packet[14], HEX); Serial.print(" byte 15  "); // prints byte 14 and byte 15 for debugging
        float v2 = (analogChannelData2 * 3.25) / 10.24; float tempC2 = (v2 - 50); // converts raw A/D signal to deg C
        float tempF2 = (tempC2 * 9 / 5) + 32; Serial.print(tempF2);Serial.println("  Temp F 2 ");Serial.println("");  // converts C to F and prints it.
        writeNumber(file, tempF2);                  // add value for tempF2  to line of data
        writeString(file, " , ");      // comma to separate readings for export to excel


Second line up from the bottom, is 'writeNumber(file, tempF2);' , This is the temperature that was derived from the raw TMP36 reading. It can go negative.

Changing that code to:

Code: Select all | TOGGLE FULL SIZE
        writeNumber(file, analogChannelData2);                  // add value for TMP36 2 to line of data
        writeString(file, " , ");      // comma to separate readings for export to excel


Produced this:

Image

Which I can work with, I will just do the math in Excel.


What, if anything, can I do to properly store the negative values on the SD card?


EDIT- Right after posting, I had an idea...maybe convert tempFx to an integer? (int)
Code: Select all | TOGGLE FULL SIZE
        writeNumber(file, int(tempF3));                  // add value for tempF3 to line of data
        writeString(file, " , ");      // comma to separate readings for export to excel


but still got the 4.2 billion reading. Rats.
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Re: Logger Shield and Negative Numbers

by fat16lib on Sun Jun 13, 2010 7:12 pm

WriteNumber's second argument is uint32_t so it does not handle negative numbers.

SdFile has Print as a parent class so you can print to a file like this:

Code: Select all | TOGGLE FULL SIZE
  file.print(tempF2);
  file.print(',');
fat16lib
 
Posts: 593
Joined: Wed Dec 24, 2008 1:54 pm

Re: Logger Shield and Negative Numbers

by Volkemon on Sun Jun 13, 2010 7:27 pm

Thanks once again, fat16lib.

I am suffering somewhat from my 'cut and paste' education.

"uint32_t" means nothing to me yet, and was in the 'unknown' category. I am learning more and more however.

I started from the SDFatWrite example, and have to learn how to use the SD library more completely. Your code sure looks a heck of a lot simpler!!!!

Even moreThanks, and on I go to learn about 'uint32_t'. Thank goodness for one more day off...
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Re: Logger Shield and Negative Numbers

by pstemari on Sun Jun 13, 2010 10:30 pm

The uint32 should be easy to work around in your favorite spreadsheet--just subtract 2^32 (4294967296) from any value greater than 2^31-1 (2147483647).
--Paul

A wholly owned subsidiary of:
Persephone: DL R+W+B C 7 X L W C++ I++ T+ A E H++ S+ V-- F+ Q P B PA+ PL
Aldebaran: DM Rt H 5 Y L- W+ C+ I++ T++ A+++ E H++ S+ V+ F++ Q+ P B++ PA- PL--
User avatar
pstemari
 
Posts: 310
Joined: Sun Mar 21, 2010 6:10 pm
Location: Seattle, WA

Re: Logger Shield and Negative Numbers

by Volkemon on Sun Jun 13, 2010 10:42 pm

LOL! Thanks for the overestimation of my current abilities. :) I am still looking to find out what a 'uint32' is... Unsigned INTeger ...32 somethings..

But your answer makes sense, and explains the LARGE number.

It might be easier just to import the readings from the TMP36, and do the temperature conversions there. Might do that.

Thank you for another bit of wisdom.
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Re: Logger Shield and Negative Numbers

by fat16lib on Sun Jun 13, 2010 10:45 pm

Just use file.print() - it will handle negative values.
fat16lib
 
Posts: 593
Joined: Wed Dec 24, 2008 1:54 pm

Re: Logger Shield and Negative Numbers

by Volkemon on Sun Jun 13, 2010 11:14 pm

I did try that, but it would not seem to convert to an integer. Returned what appeared to be the integer and decimal value all together as an integer. IE: 78.181579 degrees was sent as 78181579.

Even taking the tempF[x] value and converting it to an integer named q - int q = int(tempF[x]); and then print.file(q); printed the larger number.

I realize that this is the period before another 'breakthrough in knowledge', and I am getting closer. Just a wee bit tired, as I have been at this for 15 hours today. So... please be patient with me. ( Like you have not been already! You and ChuckM have the patience of saints.)



Did just find this, somewhat (!) enlightening..http://www.arduino.cc/cgi-bin/yabb2/YaB ... 59022445/6

Indeed it seems to be common practice (even by the arduino core team) to use the uint8_t as defined by the AVR GCC compiler for unsigned 8 bit values in core and library code.


AhHA!! Soo... uint8_t buf[10]; is an array of 10 Unsigned INTegers 8 bits in length named 'buf'. No wonder it wouldn't do a negative!
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Re: Logger Shield and Negative Numbers

by fat16lib on Sun Jun 13, 2010 11:36 pm

If you can get the correct value with
Code: Select all | TOGGLE FULL SIZE
  Serial.print(x);

for a signed variable x then
Code: Select all | TOGGLE FULL SIZE
  file.print(x);

will put the same value on the SD. The same code is used for 'print' in both cases.
fat16lib
 
Posts: 593
Joined: Wed Dec 24, 2008 1:54 pm

Re: Logger Shield and Negative Numbers

by Volkemon on Mon Jun 14, 2010 12:14 am

Well, this code:
Code: Select all | TOGGLE FULL SIZE
        tempF[a] = (tempC * 9 / 5) + 32; Serial.println(tempF[a]);//Serial.println("  Temp F");Serial.println(a);  // converts C to F and prints it.
        //writeNumber(file, tempF[a]);                  // add value for tempF of pin(pinNum) to line of data
        //writeString(file, " , ");      // comma to separate readings for export to excel
        file.print(tempF[a]);
        file.print(' , ');


Produced this on the serial monitor:

Image

and this on the SD card:

Image

I think it may just be running into the way that the different libraries deal with float numbers?
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Re: Logger Shield and Negative Numbers

by Volkemon on Mon Jun 14, 2010 12:38 am

Just making sure that I did it right last time...

This code:

Code: Select all | TOGGLE FULL SIZE
        tempF[a] = (tempC * 9 / 5) + 32; Serial.println(int(tempF[a]));//Serial.println("  Temp F");Serial.println(a);  // converts C to F and prints it.
        //writeNumber(file, tempF[a]);                  // add value for tempF of pin(pinNum) to line of data
        //writeString(file, " , ");      // comma to separate readings for export to excel
        file.print(int(tempF[a]));
        file.print(' , ');


Produced nice integers on the serial monitor.(80/81/89/81)

Image

But still the long numbers on the SD card.

Image

and didn't print the " , " between numbers...

Just making sure I didn't muck it up last time. I am pretty tired.

May call it a night and hit it early. Got one more day off.

THANK YOU for the help. I hope that my bumbling around has been entertaining :wink: I sure have been having fun learning.
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Re: Logger Shield and Negative Numbers

by fat16lib on Mon Jun 14, 2010 8:16 am

You are close! The problem now is:

Code: Select all | TOGGLE FULL SIZE
  file.print(' , ');

This will print as 11296. If you want a single character ',' remove the spaces and print
Code: Select all | TOGGLE FULL SIZE
  file.print(',');

if you want a space on each side of the comma print
Code: Select all | TOGGLE FULL SIZE
  file.print(" , ");


try the following:
Code: Select all | TOGGLE FULL SIZE
  Serial.print(' , ');
  Serial.print(',');
  Serial.println(" , ");

The result is:
11296, ,


In C++, the base for Arduino, 'a' with a single character is type char and print() treats it as ASCII. 'aa' with two or more characters is type int and print() treats it as a number.
fat16lib
 
Posts: 593
Joined: Wed Dec 24, 2008 1:54 pm

Re: Logger Shield and Negative Numbers

by Volkemon on Mon Jun 14, 2010 9:10 am

Yippee!! I was hoping a nights sleep would reveal my errors. I was getting pretty sloppy typing at that point.

THAT is one complete explanation. I was thinking the .5*C resolution of the sensors was giving the same decimal result.

Well, ran it again.

Code:

Code: Select all | TOGGLE FULL SIZE
/*
 * This sketch was started using the SdFatWrite Example and grew from there.
 *
 *
 * V5 changes the LCD to a 20x4
 *
 */

#include <SdFat.h>            // library for SD card
#include <SdFatUtil.h>        // library for SD card
#include <Wire.h>             // i2c  ' one wire ' library
#include <RTClib.h>           // real time clock library
#include <LiquidCrystal.h>    // liquid crystal library


LiquidCrystal lcd(4, 5, 6, 7, 8, 9);  // LCD/Arduino pin order: RS pin / D4, EN pin / D5, DB4 pin / D6, DB5 pin / D7, DB6 pin / D8, DB8 pin / D9  - because Data Logger Shield uses D10 - D13

RTC_DS1307 RTC;                     // start Real Time Clock

Sd2Card card;                      // start SD card functions
SdVolume volume;                  //
SdFile root;                     //
SdFile file;                    //
unsigned int linecount = 0;         // for debugging in serial monitor, and a 'heartbeat' on the LCD. unsigned to allow greater sample count.
int dataLine = 0;         // variable to control number of lines of data in each WRITExx.txt file on SD card
int packet[19];   // variable for packet size, in this case 18 bytes. (0 - 17) (1 sensor=14, 2=16,3=18 4=20,etc)


// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))               // 5/17/10 from here to "*END*" was cut and paste, and I am working on translating it :)
void error_P(const char *str)
{
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}
/*
 * Write CR LF to a file
 */
void writeCRLF(SdFile &f)            // does a carriage return in .txt file?
{
  f.write((uint8_t *)"\r\n", 2);
}

void writeNumber(SdFile &f, uint32_t n)
{
  uint8_t buf[10];   
  uint8_t i = 0;
  do {
    i++;
    buf[sizeof(buf) - i] = n%10 + '0';
    n /= 10;
  } while (n);
  f.write(&buf[sizeof(buf) - i], i);
}
/*
 * Write a string to a file
 */
void writeString(SdFile &f, char *str)
{
  uint8_t n;
  for (n = 0; str[n]; n++);
  f.write((uint8_t *)str, n);                      //     *  END  *
}


void setup(void)
{
  Wire.begin();           //enable i2c
  lcd.begin(20, 4);      // set up the LCD's number of rows and columns
  Serial.begin(9600);     //start serial port
  RTC.begin();           //Start Real Time Clock

 
  if (!card.init()) error("card.init");    // initialize the SD card
 
  if (!volume.init(card)) error("volume.init");  // initialize a FAT volume
 
  if (!root.openRoot(volume)) error("openRoot");   // open the root directory

 
  char name[] = "WRITE00.TXT";     // create a new file
  for (uint8_t i = 0; i < 100; i++) {
    name[5] = i/10 + '0';
    name[6] = i%10 + '0';
    if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;

  }
  if (!file.isOpen()) error ("file.create");
  Serial.print("Writing to: ");
  Serial.println(name);
  lcd.setCursor(0,3);
  lcd.print(name);

 


}
void readPacket() {
  if (Serial.available() > 0) {
    int b = Serial.read();
    if (b == 0x7E) {
      packet[0] = b;
      packet[1] = readByte();
      packet[2] = readByte();
      int dataLength = (packet[1] << 8) | packet[2];

      for(int i=1;i<=dataLength;i++) {
        packet[2+i] = readByte();
      }
      int apiID = packet[3];
      int SenID = (packet[4] << 8) | packet[5];
      packet[3+dataLength] = readByte(); // checksum

      printPacket(dataLength+4);

      if (apiID == 0x83) {           // if string sent has the fourth byte (= API ID) 0x83
        int s = 1;   // variable to print the readings from the XBee on the proper line of the LCD for that sensor group
        if (SenID == 0x5678){ s = 1;}   // sensor group 1
        if (SenID == 0x5679){ s = 2;}   //sensor group 2
        int analogSampleIndex = 13; // byte-1 for where analog data starts in the string
        int sigStrg = packet [6];   // read the seventh byte in the string = signal strength
        lcd.setCursor(0, 0);    // put the LCD cursor to row , column0  to start signal strength display line on LCD
        //char signal[] = "Sig-";       // added to try to disply Sig-  before signal strength on LCD
        //lcd.print(signal);            //                      ""
        lcd.print("Sig-");              // Used to work, now doesnt. Un-commented it again to see if it worked, commented out patch above. Still didnt LCD print.
        Serial.print(sigStrg);
        delay (50);  // added to see if it helped serial.print problem
        char dBm[]= "dBm";
        Serial.println(dBm); Serial.println("");   // displays signal strength on serial monitor, also adds a line return to format
        // Serial.println("  dBm  "); Serial.println("");   STOPPED WORKING
        lcd.setCursor(4, 0);    // put the LCD cursor to row3 , column0  to start signal strength display line on LCD
        lcd.print(sigStrg);         // print signal strength
        lcd.print(dBm);
        int pac = 11;
        int h = 0;  // for positioning the temp on LCD display
        int ADdata[4];
        float tempF[4];
       for (int a=1;a<5;a++) {
        ADdata[a] = (packet[pac] <<8) | packet[(pac + 1)];  // reads byte 12, shifts it over 8 bits, and appends byte 13 to it to form the raw data variable from the A/D converter reading
        Serial.println(ADdata[a]);Serial.print(" TMP36");Serial.println(a);  // prints raw A/D readingfor debugging
        int r = FreeRam();
        Serial.println(r);
        //Serial.print(packet[pac], HEX);Serial.print(" byte 12  ");Serial.print(packet[(pac + 1)], HEX); Serial.print(" byte 13  "); // prints byte 12 and byte 13 for debugging
        float v = (ADdata[a] * 3.25) / 10.24; float tempC = (v - 50); // converts raw A/D signal to deg C
        tempF[a] = (tempC * 9 / 5) + 32; Serial.println(int(tempF[a]));//Serial.println("  Temp F");Serial.println(a);  // converts C to F and prints it.
        //writeNumber(file, tempF[a]);                  // add value for tempF of pin(pinNum) to line of data
        //writeString(file, " , ");      // comma to separate readings for export to excel
        file.print(int(tempF[a]));
        file.print(" , ");
        lcd.setCursor(h, s);    // put the LCD cursor to row2 , column0  to start temp display line on LCD
         if (tempF[a] < 100 && tempF[a] > 0)        // puts a '0' before 10-99 to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        if (tempF[a] < 10 && tempF[a] >= 0)        // puts a '0' before single digits to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        lcd.print(int (tempF[a]) );         // print tempF1

        pac += 2;
        h += 5;
       
       }     
       

      }
    }
   

  }


}




void loop(void) {
 
  Serial.print(linecount); Serial.print(" start ");    // serial output for debugging
 
    for ( dataLine = 0; dataLine < 30; dataLine ++) {         // larger number (divided by PinNumMAX) determines how many lines of data per WRITExx.txt file.
   
    readPacket();

    lcd.setCursor(14, 3);           //Position cursor for linecount
    lcd.print(linecount);          // put linecount on LCD   

      Serial.println(" ");                    // puts space in when debugging                                   
      Serial.print(linecount); Serial.print("= linecount  ");  // serial print for debugging
      DateTime now = RTC.now();               // Read RTC
      Serial.print("TEST RTC ");
      Serial.print(now.hour(), DEC);
      Serial.print(":");
      Serial.print(now.minute(), DEC);        // Gets minute from RTC
      Serial.print(":");                      // puts the ":" between the minute and second
      Serial.print(now.second(), DEC);      //Gets second from RTC - for debugging
      Serial.println("   ");                  // space to format serial table better
      lcd.setCursor(12, 0);                  // shows time on top right of LCD
      lcd.print(now.hour(), DEC); lcd.print(":");    // displays current hour on LCD
      if ((now.minute()) < 10)        // puts a '0' before single digits to preserve format on LCD
      {                              //
        lcd.print("0");             //
      }                            //
      lcd.print(now.minute(), DEC); lcd.print(":");    // displays current minute on LCD
      if ((now.second()) < 10)        // puts a '0' before single digits to preserve format on LCD
      {                              //
        lcd.print("0");             //
      }                            //
      lcd.print(now.second(), DEC);     // display seconds on LCD   
      writeNumber(file, now.hour());     // timestamp hour
      writeString(file, ":");            // format time with "  :  "
      writeNumber(file, now.minute());   // timestamp minute
      writeString(file, ":");            // format time with "  :  "
      writeNumber(file, now.second());   // timestamp second
      lcd.setCursor(12, 3);    // put the LCD cursor to row4 , column12 
      lcd.print("L=");         // print L for linecount.
      writeCRLF(file);                        // goes to new line in text data file
      linecount++;                            // adavances linecount for serial debugging and LCD
   
   
     
   
    delay (2000);                         // delay to adjust overall sample rate
  }
 
  file.close();                           // close file and force write of all data to the SD card
  Serial.println("Done");                 // for debugging
  char name[] = "WRITE00.TXT";           // create a new file for next batch of data
  for (uint8_t i = 0; i < 100; i++) {    // will only do 100 SD file writes 5/17/10
    name[5] = i/10 + '0';                // the "char name" [fifth digit] = i/10 followed by a printed " 0 "
    name[6] = i%10 + '0';                // the "char name" [sixth digit] = i % (what?) followed by a " 0 "
    if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;
  }
  if (!file.isOpen()) error ("file.create");
  Serial.print("Writing to: ");
  Serial.println(name);
  lcd.setCursor(0,3);
  lcd.print(name);
}


void printPacket(int l) {
  for(int i=0;i < l;i++) {
    if (packet[i] < 0xF) {      // if the packet value is HEX F or lower
      Serial.print(0);         //print leading zero for single digit values
    }
    Serial.print(packet[i], HEX);
    Serial.print(" ");
  }
  Serial.println(" new string ");Serial.println("");
}


int readByte() {
    while (true) {
      if (Serial.available() > 0) {
      return Serial.read();
    }
  }
}
 


Results on Serial monitor:
Image

Results on SD card:

Image

Oh well, still wont print commas. Seems to have extra and missing data also.

I am going to try some earlier versions and see how they run, and what I added that messed things up. I tried to go 'step by step', and having a known state to revert to.
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Re: Logger Shield and Negative Numbers

by Volkemon on Mon Jun 14, 2010 9:50 am

Thinking with a clear mind, I ponder... What has been the biggest PITA in this project?

The RTC, or Real Time Clock on the Data Logger Shield. I commented it and the 1-wire library out... and Voila!!

Code: Select all | TOGGLE FULL SIZE
/*
 * This sketch was started using the SdFatWrite Example and grew from there.
 *
 *
 * V5 changes the LCD to a 20x4
 *
 */

#include <SdFat.h>            // library for SD card
#include <SdFatUtil.h>        // library for SD card
//#include <Wire.h>             // i2c  ' one wire ' library
//#include <RTClib.h>           // real time clock library
#include <LiquidCrystal.h>    // liquid crystal library

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);  // LCD/Arduino pin order: RS pin / D4, EN pin / D5, DB4 pin / D6, DB5 pin / D7, DB6 pin / D8, DB8 pin / D9  - because Data Logger Shield uses D10 - D13

//RTC_DS1307 RTC;                     // start Real Time Clock

Sd2Card card;                      // start SD card functions
SdVolume volume;                  //
SdFile root;                     //
SdFile file;                    //
unsigned int linecount = 0;         // for debugging in serial monitor, and a 'heartbeat' on the LCD. unsigned to allow greater sample count.
int dataLine = 0;         // variable to control number of lines of data in each WRITExx.txt file on SD card
int packet[19];   // variable for packet size, in this case 18 bytes. (0 - 17) (1 sensor=14, 2=16,3=18 4=20,etc)
int analogSamples[3];

// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))               // 5/17/10 from here to "*END*" was cut and paste, and I am working on translating it :)
void error_P(const char *str)
{
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}
/*
 * Write CR LF to a file
 */
void writeCRLF(SdFile &f)            // does a carriage return in .txt file?
{
  f.write((uint8_t *)"\r\n", 2);
}
/*
 * Write an unsigned number to a file
 */
void writeNumber(SdFile &f, uint32_t n)
{
  uint8_t buf[10];
  uint8_t i = 0;
  do {
    i++;
    buf[sizeof(buf) - i] = n%10 + '0';
    n /= 10;
  } while (n);
  f.write(&buf[sizeof(buf) - i], i);
}
/*
 * Write a string to a file
 */
void writeString(SdFile &f, char *str)
{
  uint8_t n;
  for (n = 0; str[n]; n++);
  f.write((uint8_t *)str, n);                      //     *  END  *
}


void setup(void)
{
  //Wire.begin();           //enable i2c
  lcd.begin(20, 4);      // set up the LCD's number of rows and columns
  Serial.begin(9600);     //start serial port
  //RTC.begin();           //Start Real Time Clock
  //Serial.println();                                 //
  //Serial.println("Type any character to start");   //
  //while (!Serial.available());                    // comment out these 3 lines to 'autostart'
 
  if (!card.init()) error("card.init");    // initialize the SD card
 
  if (!volume.init(card)) error("volume.init");  // initialize a FAT volume
 
  if (!root.openRoot(volume)) error("openRoot");   // open the root directory

 
  char name[] = "WRITE00.TXT";     // create a new file
  for (uint8_t i = 0; i < 100; i++) {
    name[5] = i/10 + '0';
    name[6] = i%10 + '0';
    if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;

  }
  if (!file.isOpen()) error ("file.create");
  Serial.print("Writing to: ");
  Serial.println(name);
  lcd.setCursor(0,3);
  lcd.print(name);

 


}
void readPacket() {
  if (Serial.available() > 0) {
    int b = Serial.read();
    if (b == 0x7E) {
      packet[0] = b;
      packet[1] = readByte();
      packet[2] = readByte();
      int dataLength = (packet[1] << 8) | packet[2];

      for(int i=1;i<=dataLength;i++) {
        packet[2+i] = readByte();
      }
      int apiID = packet[3];
      int SenID = (packet[4] << 8) | packet[5];
      packet[3+dataLength] = readByte(); // checksum

      printPacket(dataLength+4);

      if (apiID == 0x83) {           // if string sent has the fourth byte (= API ID) 0x83
        int s = 1;
        if (SenID == 0x5678){ s = 1;   }
        if (SenID == 0x5679){ s = 2;}
        int analogSampleIndex = 13; // byte-1 for where analog data starts in the string
        int sigStrg = packet [6];   // read the seventh byte in the string = signal strength
        lcd.setCursor(0, 0);    // put the LCD cursor to row , column0  to start signal strength display line on LCD
        char signal[] = "Sig-"; lcd.print(signal);
        Serial.print(sigStrg);
        delay (50);  // added to see if it helped serial.print problem
        char dBm[]= "dBm";
        Serial.println(dBm); Serial.println("");   // displays signal strength on serial monitor, also adds a line return to format
        // Serial.println("  dBm  "); Serial.println("");   STOPPED WORKING
        lcd.setCursor(4, 0);    // put the LCD cursor to row3 , column0  to start signal strength display line on LCD
        lcd.print(sigStrg);         // print signal strength
        lcd.print(dBm);
       
       
        int analogChannelData = (packet[11] <<8) | packet[12];  // reads byte 12, shifts it over 8 bits, and appends byte 13 to it to form the raw data variable from the A/D converter reading
        Serial.print(analogChannelData);Serial.println(" TMP36 1  ");Serial.println("");  // prints raw A/D readingfor debugging
        Serial.print(packet[11], HEX);Serial.print(" byte 12  ");Serial.print(packet[12], HEX); Serial.print(" byte 13  "); // prints byte 12 and byte 13 for debugging
        float v = (analogChannelData * 3.25) / 10.24; float tempC = (v - 50); // converts raw A/D signal to deg C
        float tempF = (tempC * 9 / 5) + 33; Serial.print(tempF);Serial.println("  Temp F  ");Serial.println("");  // converts C to F and prints it.33 upper sensor calibrate
        writeNumber(file, tempF);                  // add value for tempF of pin(pinNum) to line of data
        writeString(file, " , ");      // comma to separate readings for export to excel
        lcd.setCursor(0, s);    // put the LCD cursor to row2 , column0  to start temp display line on LCD
         if (tempF < 100 && tempF > 0)        // puts a '0' before 10-99 to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        if (tempF < 10 && tempF >= 0)        // puts a '0' before single digits to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        lcd.print(int (tempF) );         // print tempF1
       
        int analogChannelData2 = (packet[13] <<8) | packet[14];  // reads byte 14, shifts it over 8 bits, and appends byte 15 to it to form the raw data variable from the A/D converter reading
        Serial.print(analogChannelData2);Serial.println(" TMP36 2 reading ");Serial.println("");  // prints raw A/D readingfor debugging
        Serial.print(packet[13], HEX);Serial.print(" byte 14  ");Serial.print(packet[14], HEX); Serial.print(" byte 15  "); // prints byte 14 and byte 15 for debugging
        float v2 = (analogChannelData2 * 3.25) / 10.24; float tempC2 = (v2 - 50); // converts raw A/D signal to deg C
        float tempF2 = (tempC2 * 9 / 5) + 35; Serial.print(tempF2);Serial.println("  Temp F 2 ");Serial.println("");  // converts C to F and prints it.35 for sensor calibration upper
        writeNumber(file, tempF2);                  // add value for tempF of pin(pinNum) to line of data
        writeString(file, " , ");      // comma to separate readings for export to excel
        lcd.setCursor(5, s);    // put the LCD cursor to row2 , column4  for temp display line on LCD
         if (tempF2 < 100 && tempF2 > 0)        // puts a '0' before 10-99 to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        if (tempF2 < 10 && tempF2 >= 0)        // puts a '0' before single digits to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        lcd.print(int (tempF2));         // print tempF2
       
        int analogChannelData3 = (packet[15] <<8) | packet[16];  // reads byte 16, shifts it over 8 bits, and appends byte 17 to it to form the raw data variable from the A/D converter reading
        Serial.print(analogChannelData3);Serial.println(" TMP36 3 reading ");Serial.println("");  // prints raw A/D readingfor debugging
        Serial.print(packet[15], HEX);Serial.print(" byte 16  ");Serial.print(packet[16], HEX); Serial.print(" byte 17  "); // prints byte 16 and byte 17 for debugging
        float v3 = (analogChannelData3 * 3.25) / 10.24; float tempC3 = (v3 - 50); // converts raw A/D signal to deg C
        float tempF3 = (tempC3 * 9 / 5) + 33; Serial.print(tempF3);Serial.println("  Temp F 3 ");Serial.println("");  // converts C to F and prints it. 33 for sensor calibration upper
        writeNumber(file, tempF3);                  // add value for tempF of pin(pinNum) to line of data
        writeString(file, " , ");      // comma to separate readings for export to excel
        lcd.setCursor(15, s);    // put the LCD cursor to row2 , column8  for display line on LCD
         if (tempF3 < 100 && tempF3 > 0)        // puts a '0' before 10-99 to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        if (tempF3 < 10 && tempF3 >= 0)        // puts anot '0' before single digits to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        lcd.print(int (tempF3) );         // print tempF3
       
        int analogChannelData4 = (packet[17] <<8) | packet[18];  // reads byte 18, shifts it over 8 bits, and appends byte 19 to it to form the raw data variable from the A/D converter reading
        Serial.print(analogChannelData4);Serial.println(" TMP36 4 reading ");Serial.println("");  // prints raw A/D readingfor debugging
        Serial.print(packet[17], HEX);Serial.print(" byte 18  ");Serial.print(packet[18], HEX); Serial.print(" byte 19  "); // prints byte 18 and byte 19 for debugging
        float v4 = (analogChannelData4 * 3.25) / 10.24; float tempC4 = (v4 - 50); // converts raw A/D signal to deg C
        float tempF4 = (tempC4 * 9 / 5) + 33; Serial.print(tempF4);Serial.println("  Temp F 4 ");Serial.println("");  // converts C to F and prints it. 33 to calbrate sensor upper
        writeNumber(file, tempF4);                  // add value for tempF of pin(pinNum) to line of data
        writeString(file, " , ");      // comma to separate readings for export to excel
        lcd.setCursor(10, s);    // put the LCD cursor to row2 , column8  for display line on LCD
         if (tempF4 < 100 && tempF4 > 0)        // puts a '0' before 10-99 to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        if (tempF4 < 10 && tempF4 >= 0)        // puts a '0' before single digits to preserve format on LCD, allows for - sign display
      {                              //
        lcd.print("0");             //
      }                            //
        lcd.print(int (tempF4) );         // print tempF4
       
        for(int i=0;i<4;i++) {        // change middle number to number of sensors?
          if ((analogChannelData >> i) & 1) {
            analogSamples[i] = (packet[analogSampleIndex] << 8) | packet[analogSampleIndex+1];
            analogSampleIndex += 2;
          } else {
            analogSamples[i] = -1;
          }
        }
      }
    }
   

  }


}


void printPacket(int l) {
  for(int i=0;i < l;i++) {
    if (packet[i] < 0xF) {      // if the packet value is HEX F or lower
      Serial.print(0);         //print leading zero for single digit values
    }
    Serial.print(packet[i], HEX);
    Serial.print(" ");
  }
  Serial.println(" new string ");Serial.println("");
}


int readByte() {
    while (true) {
      if (Serial.available() > 0) {
      return Serial.read();
    }
  }
}
 


void loop(void) {
  int pinNum = 1;      // variable to determine which sensor value is read.
  int pinNumMAX = 3;    // variable to determine how many temperature sensors are in the stream 
  Serial.print(linecount); Serial.print(" start ");    // serial output for debugging
 
    for ( dataLine = 0; dataLine < 30; dataLine ++) {         // larger number (divided by PinNumMAX) determines how many lines of data per WRITExx.txt file.
   
    readPacket();

    lcd.setCursor(14, 3);           //Position cursor for linecount
    lcd.print(linecount);          // put linecount on LCD   
    pinNum = pinNum + 1;                       // advances to next pin in line of data
    if (pinNum >=pinNumMAX)                    // check to see if pin number is at the end - ' if ' it is, run the following. If not, skips down to delay (1000) {}
    {
      pinNum = 1;                              // reset pinNum to get ready for new line of data
      Serial.println(" ");                    // puts space in when debugging                                   
      Serial.print(linecount); Serial.print("= linecount  ");  // serial print for debugging
   /*   DateTime now = RTC.now();               // Read RTC
      Serial.print("TEST RTC ");
      Serial.print(now.hour(), DEC);
      Serial.print(":");
      Serial.print(now.minute(), DEC);        // Gets minute from RTC
      Serial.print(":");                      // puts the ":" between the minute and second
      Serial.print(now.second(), DEC);      //Gets second from RTC - for debugging
      Serial.println("   ");                  // space to format serial table better
      lcd.setCursor(12, 0);                  // shows time on top right of LCD
      lcd.print(now.hour(), DEC); lcd.print(":");    // displays current hour on LCD
      if ((now.minute()) < 10)        // puts a '0' before single digits to preserve format on LCD
      {                              //
        lcd.print("0");             //
      }                            //
      lcd.print(now.minute(), DEC); lcd.print(":");    // displays current minute on LCD
      if ((now.second()) < 10)        // puts a '0' before single digits to preserve format on LCD
      {                              //
        lcd.print("0");             //
      }                            //
      lcd.print(now.second(), DEC);     // display seconds on LCD   
      writeNumber(file, now.hour());     // timestamp hour
      writeString(file, ":");            // format time with "  :  "
      writeNumber(file, now.minute());   // timestamp minute
      writeString(file, ":");            // format time with "  :  "
      writeNumber(file, now.second());   // timestamp second  */
      lcd.setCursor(12, 3);    // put the LCD cursor to row4 , column12 
      lcd.print("L=");         // print L for linecount.
      writeCRLF(file);                        // goes to new line in text data file
      linecount++;                            // adavances linecount for serial debugging and LCD  */
    }
   
     
   
    delay (1000);                         // delay to adjust overall sample rate
  }
 
  file.close();                           // close file and force write of all data to the SD card
  Serial.println("Done");                 // for debugging
  char name[] = "WRITE00.TXT";           // create a new file for next batch of data
  for (uint8_t i = 0; i < 100; i++) {    // will only do 100 SD file writes 5/17/10
    name[5] = i/10 + '0';                // the "char name" [fifth digit] = i/10 followed by a printed " 0 "
    name[6] = i%10 + '0';                // the "char name" [sixth digit] = i % (what?) followed by a " 0 "
    if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;
  }
  if (!file.isOpen()) error ("file.create");
  Serial.print("Writing to: ");
  Serial.println(name);
  lcd.setCursor(0,3);
  lcd.print(name);
}


Serial Window NICE and tidy-

Image

SD card working great. LCD monitor also working *perfectly*.(no pics, however. I can get one if desired.)

Image

Missing lines of data are OK - I put the remote XBee down to a transmission every 3 seconds back when I thought it was a RAM issue. The program is sampling before there is data in the buffer. EZ fix.

Well, down to the RTC, RTC library or the Wire library. I will most certainly post results. I do need the timestamp, and would like not to have to set the time every use/reset!
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Re: Logger Shield and Negative Numbers

by fat16lib on Mon Jun 14, 2010 9:58 am

Looks like memory overwrite problems.
You have:
Code: Select all | TOGGLE FULL SIZE
   int packet[19];

But appear to store 20 values:

Initial 7E, two for length, 16 for data, and one for check sum for a total of twenty value.

You should put a test in to make sure
Code: Select all | TOGGLE FULL SIZE
int dataLength = (packet[1] << 8) | packet[2];

is not too large for the array packet[]. You need to check/test all array indexes for range.
fat16lib
 
Posts: 593
Joined: Wed Dec 24, 2008 1:54 pm

Re: Logger Shield and Negative Numbers

by Volkemon on Mon Jun 14, 2010 10:00 am

That isnt 20 bytes- packet[0] - packet[19] ?
Livin' , learnin' , lovin' and laffin'. Thanks for the help!
Image
User avatar
Volkemon
 
Posts: 127
Joined: Mon May 10, 2010 8:24 pm
Location: Melbourne FL USA

Please be positive and constructive with your questions and comments.