Go Down

Topic: Analogread problem in 1.5.2 as well as 1.5.5-r2 (Read 535 times) previous topic - next topic

billarduino

I don't *think* this particular bug is already on here, but if so I apologize. I have recently found that, when reading from A0, A1, and A2, that A0 & A1 are fine, but A2 seems to periodically report zeros. I thought it could be a temporary thing, so I changed my single read (after a read and a few ms delay to have a clean change from reading the other inputs) to the sum of 8 reads. I still would get a couple of runs through the loop that were correct and then one or more that were zero (meaning 8 zero reads in a row, really). After a few runs of zero, it would go back to being correct. Lather, rinse, repeat.

I connected an Analog Discovery box to the circuit to make sure that the digital pot I was using was not misbehaving, and it wasn't. With no other ideas, I replaced the DUE with a MEGA 2560 and Arduino 1.0.1. Other than commenting out the "analogreadresolution", no changes. The MEGA seems to work perfectly. Several dozen of these loops have completed without a single zero reading.

MarkT

Can you post your code so others can try to reproduce the problem (or at least
confirm if its a known one or a new one).
[ I won't respond to messages, use the forum please ]

billarduino

Well, it's not pretty, but...

Code: [Select]
#include <TinyGPS.h>
TinyGPS gps;
static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
volatile int datcol=0, val=0, sum = 0;    
volatile long tim=0, bigsum=0, bigind=0, bigsum1=0, oldbigsum1=0, resvalsum=0, ckint1=0, holdcons0=0;
long cons0=0, tmptim=0, llong=0, llat=0;
volatile long rtc=0, gpsc=0, savrtc=0, savgps=0;
int ar0=0, ar1=0;
long deadtime=0;
int agewarn=0, GPSPWR=7, EQINT=8, RTCINT=9, GPSINT=10, CS=2, CLK=3, UD=4, EQINTLED=32;
int x=0, inByte0='0', inByte1='0', inByte2='0', sval=0;
volatile int inByteTot=0, newinByteTot=0;
unsigned long evArray[4]={0,0,0,0};
int evarraycount=0;

void setup() {
Serial.begin(115200);
Serial2.begin(9600);
pinMode(GPSPWR,OUTPUT);
pinMode(EQINT,INPUT);
pinMode(EQINTLED,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(UD,OUTPUT);
pinMode(CLK,OUTPUT);

inByteTot=40;
chgpot();
digitalWrite(GPSPWR,HIGH);
digitalWrite(EQINTLED,LOW);
attachInterrupt(EQINT,eq,CHANGE);
digitalWrite(EQINT,HIGH);
attachInterrupt(RTCINT,rtcsub,RISING);
attachInterrupt(GPSINT,gpssub,RISING);

analogReadResolution(12);
}

void loop()
{
 int incomingByte=0;
 int ii=0;
 bool newdata = false;
 unsigned long start = millis();
  // Every minute we print an update
  bigsum=0;
  bigind=0;
  bigsum1=0;
  cons0=0;
  holdcons0=0;
 while (millis() - start < 60000)
 {
 if (datcol>0){goto checkeq;} //break out of loop searching for gps data if EQ interrupt triggered
 if (Serial.available()){ //Need to change potentiometer setting
 digitalWrite(EQINTLED,LOW);
     inByte0=Serial.read();
     if (Serial.available()) {
     inByte1=Serial.read();
     if (Serial.available()){
       inByte2=Serial.read();
     }
   }
    newinByteTot=(inByte2-'0')+ (10*(inByte1-'0')) + (100*(inByte0-'0'));
    inByte0='0';
    inByte1='0';
    inByte2='0';
    if(newinByteTot>10 && newinByteTot<110){
      inByteTot=newinByteTot; //only make change if sent a reasonable input
    }
    chgpot();
 }  //End of loop changing pot setting
 
  if (feedgps()){
     newdata = true;
  }
  ar0=analogRead(0);
  delay(4);
  ar1=analogRead(1);
  bigsum+= ar0;
  bigsum1+= ar1;
  if(ar0==0)
  {
  cons0++;
    if(cons0>holdcons0)
    {
    holdcons0=cons0;
    }
  }
  else
  {
    cons0=0;
  }
  delay(1);
  bigind++;
 } //end of while loop that completes every minute

 gpsdump(gps);
checkeq:
 if (datcol>0)
 { ckint1=analogRead(1); // check to see if interrupt was random spike or
   delay(2);      // if amplified signal is actually significantly larger than
   ckint1=analogRead(1);    // previous background
   if(abs((8*ckint1)-oldbigsum1)<100) goto cancel; // get out if not real EQ
   detachInterrupt(EQINT);
   digitalWrite(EQINTLED,HIGH);
   Serial.print("< EQ start ");
   Serial.print(savgps);
   Serial.print(" gps and ");
   Serial.print(savrtc);
   Serial.println(" rtc >");
   while(ii<1000)
       {
         ii++;
         Serial.print("< ");
       sum = 0;
       for (int j = 0; j < 8; j++)
         {
         sum += analogRead(0);
         delay(2);
         }
         Serial.print(sum);
         Serial.print(" ");
         tmptim=millis();
         Serial.print(tmptim);
         Serial.print(" ");
         Serial.print(rtc);
         Serial.print(" ");
         sum=analogRead(1);
         delay(10);
         sum = 0;
         for (int j = 0; j < 8; j++)
             {
             sum += analogRead(1);
             delay(2);
             }
         Serial.print(sum);
         Serial.print(" ");
         tmptim=millis();
         Serial.print(tmptim);
         Serial.print(" ");
         Serial.print(rtc);
         Serial.print(" ");
         Serial.print(gpsc);
         Serial.println(" >");
       } //End of while ii<1000 loop
         Serial.println("< xxx xxx EQ Data Ended xxx xxx >");  // Last
         evArray[evarraycount & 3] = millis(); //update time of most recent EQ int
         evarraycount++; //move pointer to next array element
         if (((millis() - evArray[evarraycount & 3] ) < 1800000) && (inByteTot<110)){//if oldest EQ int < 30 m old and pot not near its limit, change pot
           inByteTot++;
           chgpot();
         }
         datcol=0;
         digitalWrite(EQINTLED,LOW);
         //attachInterrupt(EQINT,eq,HIGH); Replace this line by next two for
         attachInterrupt(EQINT,eq,CHANGE); //less touchy interrupts
         digitalWrite(EQINT,HIGH);

        /* flag++;
        if(flag<4){
          attachInterrupt(EQINT,eq,HIGH);
        }*/
       
 }    //end datcol>0 loop
cancel:
      if(agewarn>0 && (millis()-deadtime)>600000)  //GPS down AND down >10 min
      {        
       digitalWrite(GPSPWR,LOW);    //power cycle
       delay(10000);
       digitalWrite(GPSPWR,HIGH);
       agewarn=0; //reset alarm trip
      }
}    //main loop
static void gpsdump(TinyGPS &gps)
{
 float flat, flon;
 unsigned long age, date, time, chars = 0;
 unsigned short sentences = 0, failed = 0;
 gps.f_get_position(&flat, &flon, &age);
 Serial.print("< ");
 if (datcol > 0){ return;}
 llat=100000*flat;
 print_int(llat,TinyGPS::GPS_INVALID_F_ANGLE,8);
 if (datcol > 0){ return;}
 llong=100000*flon;
 print_int(llong,TinyGPS::GPS_INVALID_F_ANGLE,9);
 if (datcol > 0){ return;}
 Serial.print(age);
 Serial.print(" ");
 if (datcol > 0){ return;}
 if(age<10000)
 {
   agewarn=0;
 }
 if(age>10000  && agewarn==0)
 {  
  deadtime=millis(); //get time of first noticing dead gps
  agewarn=1;
 }
 print_date(gps);
 gps.stats(&chars, &sentences, &failed);
 Serial.println(" >");
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
 char sz[32];
 if (val == invalid)
   strcpy(sz, "*******");
 else
   sprintf(sz, "%ld", val);
 sz[len] = 0;
 for (int i=strlen(sz); i<len; ++i)
   sz[i] = ' ';
 if (len > 0)
   sz[len-1] = ' ';
 Serial.print(sz);
 feedgps();
}

static void print_date(TinyGPS &gps)
{
 int year;
 int loopi;
 byte month, day, hour, minute, second, hundredths;
 unsigned long age;
 gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
 if (age == TinyGPS::GPS_INVALID_AGE)
   Serial.print("******* ******* ");
 else
 {
   char sz[32];
   sprintf(sz, "%02d%02d%02d %02d %02d %02d %02d ",
       month, day, year, hour, minute, second,hundredths);
   Serial.print(sz);
 }
 Serial.print(age);
 Serial.print(" ");
 Serial.print(rtc);
 Serial.print(" ");
 Serial.print(gpsc);
 resvalsum=analogRead(2);
 resvalsum=0;
 delay(20);
            for (int jjj = 0; jjj < 10; jjj++)
             {
             resvalsum+=analogRead(2); //Pot wiper
             delay(2);
             }
 Serial.print(" ");
 Serial.print(resvalsum);
 Serial.print(" ");
 Serial.print(holdcons0);
 Serial.print(" ");
 Serial.print(bigsum/bigind);
 Serial.print(" ");
   Serial.print(bigsum1/bigind);
 Serial.print(" ");
 Serial.print(inByteTot);
 feedgps();
 oldbigsum1=bigsum1;
}

static void print_str(const char *str, int len)
{
 int slen = strlen(str);
 for (int i=0; i<len; ++i)
   Serial.print(i<slen ? str[i] : ' ');
 feedgps();
}

static bool feedgps()
{
 while (Serial2.available())
 {
   if (gps.encode(Serial2.read()))
     return true;
 }
 return false;
}

void chgpot()
{
     x=0;
     detachInterrupt(EQINT);
     digitalWrite(CS,LOW);     //Low to change resistance, high otherwise
     digitalWrite(UD,LOW);    //UD Low = Decrement = lower voltage, High = Increment
     digitalWrite(CLK,LOW);  //CLK->High, CLK->Low as fast as possible = change resistance 1 unit
     while(x<140){ //Run Vout of Pot all the way to 0 V min to ensure known starting pos
        digitalWrite(CLK,HIGH);
        digitalWrite(CLK,LOW);  
        x++;
        delay(1);
     }
     digitalWrite(EQINTLED,HIGH);
     x=0;
     digitalWrite(UD,HIGH);
     digitalWrite(CLK,LOW);
     while(x<inByteTot){
        digitalWrite(CLK,HIGH);
        digitalWrite(CLK,LOW);  
        x++;
        delay(1);
     }
     attachInterrupt(EQINT,eq,CHANGE); //less touchy interrupts
     digitalWrite(EQINT,HIGH);
     digitalWrite(EQINTLED,LOW);
     digitalWrite(CS,HIGH); // No more writes to dig pot for now
}

void eq()
{
savrtc=rtc;
savgps=gpsc;
tim = millis();
val=digitalRead(EQINT);
if(val==1){
datcol=1;
}
}
void gpssub()
{
gpsc++;
rtc=0;
}
void rtcsub()
{
rtc++;
}


Again, it will work fine for a few minutes ( = a few loops) and then report zeros for the A2 read, called resvalsum in the code. After one to several loops of that, it will return to normal for a minute or a few, and then back to zeros, alternating like that as long as I leave it running. When I program the MEGA with this, it's fine.

Go Up