Go Down

Topic: Analogue pin keeps dropping to zero... (Read 1 time) previous topic - next topic

0x10c

Hello,

  I'm working on a demo P+I tacho-generator based control system using an Uno, 2x 540 motôrs (one driven, one as an rpm to V transducer with the motor voltage sensed via a potential divider made up of 2x 10K resistors) and a 60A radio control ESC.  The motor is being driven from a 7V 2.5A PSU whilst the Uno is being powered from USB - all the earths are common (motor / ESC / tacho-gen / PSU / USB).

  The system is fairly simple - I'm reading a a set-point from a 4K7 pot, reading in the voltage off the motor, calculating the error then using the SERVO library to output a PWM signal to the ESC, which drives the motor.  I'm also calculating the summed error and feeding integral action into the mix, as well.

  Everything seems to be going fine, but every thirty seconds, the pin the sensing motor (i.e. the tacho-gen via the potential divider) is connected to resets to zero, throwing the whole system back to the start.  The Uno isn't resetting, as I'm using the serial monitor to log the time, PV, SP, Error and CV and it's only the PV (i.e. the tacho-gen output)  that falls to zero; the time (from millis()) keeps counting up as expected.

  I've connected a DVM across the tacho-gen and have determined that it's not the culprit - it's generating about 1.5-2V in the speed range I'm testing at and doesn't suddenly drop out or anything.

  I've read that some PC applications can cause the Arduino to reset by sending query packets out onto the USB, but I'm fairly sure that's not what's happening here, as the Uno millis() doesn't reset.  I'm sure I read somewhere that the Arduino ADC powers down or resets or something after some time period - my SP pot doesn't fall to zero, though, only the tacho-gen feed.

  Every 30 seconds like clockwork...there's nothing in my code that uses that time period, unless its in the servo library...any ideas what it might be?

  Thanks for any suggestions :)


Code: [Select]

#include <Servo.h>

const int pinESC = 9;
const int pinSP = A0;
const int pinPV = A1;
const int pinLED_G = 3;
const int pinLED_Y = 4;

Servo myservo;  //create servo object to control the ESC

int iSP = 0;
int iPV_raw = 0;  //raw ADC value
int iPV = 0;      //average PV value
int iErr = 0;
int iCV = 0;
int iSumErr = 0;

unsigned long lTimer;   //logging timer
unsigned long iTimer;   //integral timer
unsigned long sTimer;   //stdby timer
unsigned long fTimer;   //flash timer

int Tl = 100;           //logging time period
int Ti = 100;            //integral time period
int Tf = 500;           //flash time period
int Ts = 5000;          //stdby time period
float Ki = 0.005;         //integral gain
float Kp = 0.4;        //proportional gain

int iArrMax = 100;      //averaging filter sample size
int iIndexPV = 0;
int iSumPV = 0;
int arrPV[100];

bool bStdby = false;
bool bFlash = false;

void setup() {
  Serial.begin(9600);
 
  pinMode(pinPV,INPUT);     //PV : tachogen voltage
  pinMode(pinSP,INPUT);     //SP : right hand pot
  pinMode(pinLED_G,OUTPUT);
  pinMode(pinLED_Y,OUTPUT);

  //initialise the PV array
  for(int i = 0 ; i < 100 ; i++) {
    arrPV[i] = 0;
  }
 
  myservo.attach(9);        //attaches the ESC on pin 9 to the servo object
  //Serial.print("ConfigESC");
  //configESC();              //goes through what's possibly the setup routine for the ESC
  //Serial.println("Done");

  iTimer = millis();
  lTimer = millis();
  sTimer = millis();
  fTimer = millis();
}

void loop() {
  iSP = analogRead(pinSP);
  iSP = map(iSP,15,1013,0,1023); // create deadzones at either extreme
  iSP = max(iSP,0);
  iSP = min(iSP,1023);

 
  //recursive filter for PV
  iSumPV -= arrPV[iIndexPV];                    // subtract the PV from 100 samples ago - modulo the (index + 1) with 100 so 100 = 0
  arrPV[iIndexPV] = analogRead(pinPV);          // put the current reading in the array
  iSumPV += arrPV[iIndexPV];                    // add the current PV to the running sum
  iIndexPV++;                                   // increment the array index
  if(iIndexPV >= iArrMax) {
    iIndexPV = 0;                               // reset the array index
  }
  iPV = iSumPV / iArrMax;                       // calculate the average PV value
  //end of recursive filter for PV

  iErr = iSP - iPV;
 
  //Integral Action
  if(millis() >= (iTimer + Ti)) {
    iSumErr += iErr;
    iTimer = millis();    //reset the integral timer
  }

  iCV = (Kp * iErr) + (Ki * iSumErr);   //calculate P+I control action

  iCV = min(iCV,1023);          //limit iCV to < 1024
  iCV = max(iCV,0);             //limit iCV to > -1
  iCV = map(iCV,0,1023,90,180);

  if((millis() >= (lTimer + Tl)) && (!bStdby)) {
    Serial.print(millis());
    dLog(iSP,false);
    dLog(iPV,false);
    dLog(iErr,false);
    dLog(iCV,true);
    lTimer = millis();    //reset the log timer
  }

  if(iSP > 0) {
    digitalWrite(pinLED_G,HIGH);
    //digitalWrite(pinLED_Y,LOW);
    bStdby = false;
    sTimer = millis();
    //iAvgCnt = 0;        //reset the PV average counter
  }

  if(millis() >= (sTimer + Ts)) {
    if(iSP == 0) {
      bStdby = true;
      Serial.println("<<< Standby >>>");
      myservo.write(90); //zero throttle
      digitalWrite(pinLED_G,LOW);
      digitalWrite(pinLED_Y,HIGH);
    }
    sTimer = millis();
  }

  if(millis() >= fTimer + Tf) {
    bFlash = !bFlash;
    fTimer = millis();
  }

  myservo.write(iCV);
  //delay(10);
}

void dLog(int iSig, bool bEOL) {
  digitalWrite(pinLED_Y,bFlash);
  if(!bEOL) {
    Serial.print("\t");
    Serial.print(iSig);
  } else {
    Serial.print("\t");
    Serial.println(iSig);
  }
}

void configESC() {
  digitalWrite(pinLED_Y,HIGH);
  myservo.write(180); //full throttle
  wait(3);
  myservo.write(0); //full reverse throttle
  wait(3);
  myservo.write(90); //zero throttle
  wait(3);
  digitalWrite(pinLED_Y,LOW);
}

void wait(int seconds){
  for(int a = 0;a < seconds;a++) {
    Serial.print(".");
    delay(1000);
  }
}

Robin2

You need to make a pencil drawing showing all the connections and post a photo of the drawing.

2.5 amps seems very small for a 540 motor - I would expect that to be able to take 10 or 20 amps without breaking a sweat.

I used to have a much smaller (cheap, simple, brushed) motor in an R/C plane and it could take 9 amps.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

0x10c

Hi,

  thanks for your thoughts - I'll sketch the system and upload it...

  I'm not driving the 540 that hard and it's under practically no load - I tend to find brushed motors draw nothing like the current of brushless motors, anyway.  That said, it's not the ESC dropping out, it's the arduino - the driven motor is effectively isolated from the Uno by the ESC.

  All the best :)

MarkT

Use long, not int, for iSumPV and it won't keep overflowing.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

0x10c

Ah ha!  Well spotted!

 Thanks very much for that - I've changed both iSumPV and iSumErr to longs and that's apparently problem solved...annoyingly, I've just spent ages drawing my system setup :(

 I should have known it was my code and not maligned the Arduino...I guess that's what they call a picnic error... :)

  Thanks for your help!

MarkT

At least you posted your code!  Hope its all fine now.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up