Go Down

Topic: Analog input causes program to fail (Read 692 times) previous topic - next topic

pjfweeks

My program utilizes a microcontroller (a Teensy 2.0 using the Arduino IDE) to control an 8-LED array. Analog input from one 50K potentiometer (sensorPin) determines the speed at which the LEDs transition from one to the next in series. Input from a second 50K pot (potPin) determines how long that series is (from 1 to 8 LEDs in operation). The first pot, controlling speed, works fine. The second works well, but only if it is turned slowly. If it is turned too quickly, the Teensy board LED flashes red and the code breaks. LEDs stop blinking entirely, and will flash randomly every 10 or 20 seconds. Is this some sort of issue with transitioning between analogRead value limits? Is there a way to prevent this, or do I just have to turn the pot very slowly?

Code: [Select]

int potPin = A1; // max pin pot
int potValue = 0;
int sensorPin = A0;    // select the input pin for the potentiometer
int sensorValue = 0; 
int ledPin = 2;      // select the pin for the LED
int maxPin = 0;


void setup() {
  Serial.begin(9600);
  pinMode(sensorPin, INPUT);
  pinMode(potPin, INPUT);
  pinMode(ledPin, OUTPUT); 
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
}

void loop () {
  sensorValue = analogRead(sensorPin);
  potValue = analogRead(potPin);
  Serial.println(potValue);
     
  digitalWrite(ledPin, HIGH); 
 
  delay(sensorValue);         
       
  digitalWrite(ledPin, LOW);   
   
ledPin++;

  if (ledPin == maxPin) {ledPin = 2; }
 
  if (maxPin < 2) {maxPin = 10; }
 
  if ((potValue <= 0) && (potValue <= 126)) {maxPin = 3; }
  if ((potValue >= 127) && (potValue <= 253)) {maxPin = 4;}
  if ((potValue >= 254) && (potValue <= 380)) {maxPin = 5;}
  if ((potValue >= 381) && (potValue <= 507)) {maxPin = 6;} 
  if ((potValue >= 508) && (potValue <= 634)) {maxPin = 7;}
  if ((potValue >= 635) && (potValue <= 761)) {maxPin = 8;}
  if ((potValue >= 762) && (potValue <= 888)) {maxPin = 9;}
  if (potValue >= 889) {maxPin = 10;}
 
}

robtillaart

Do a dummy read to give the ADC (which is multiplexed for all 6 lines) some time to adjust, or do some averaging over multiple measurements.

furthermore the map() function eases the mapping of the potvalue to LED range.

applied to your code (not tested to compile )
Code: [Select]

int potPin = A1; // max pin pot
int potValue = 0;
int sensorPin = A0;    // select the input pin for the potentiometer
int sensorValue = 0; 
int ledPin = 2;      // select the pin for the LED
int maxPin = 0;

void setup()
{
  Serial.begin(115200);  // why only 9600
  pinMode(sensorPin, INPUT);
  pinMode(potPin, INPUT);
  pinMode(ledPin, OUTPUT);

  for (int pin=2; pin<10; pin++) pinMode(pin, OUTPUT);
}

void loop ()
{
  sensorValue = 0;
  for (int i=0; i < 16; i++) sensorValue += analogRead(sensorPin); 
  sensorValue /= 16;
  Serial.print("sensorValue = ");
  Serial.println(sensorValue );

  potValue = 0;
  for (int i=0; i < 16; i++) potValue += analogRead(potPin); 
  potValue /= 16;
  Serial.print("Potvalue = ");
  Serial.println(potValue);
     
  digitalWrite(ledPin, HIGH); 
  delay(sensorValue);
         
  digitalWrite(ledPin, LOW);   
  delay(sensorValue);  // missed this one?
   
  ledPin++;
  if (ledPin == maxPin) ledPin = 2;
 
  maxpin = map(potValue, 0, 1023, 2, 10);  // as the multiple if then elses are in fact a linear function
}



finally some remarks on the original code

if ((potValue <= 0)   is a semantic bug  as potvalue can never be smaller than 0 from the ADC reading

furthermore the multiple if then could be simplified to nested ... if then else if ... (
Code: [Select]

  if (potValue <= 126)) {maxPin = 3; }
  else if (potValue <= 253)) {maxPin = 4;}
  else if (potValue <= 380)) {maxPin = 5;}
  else if (potValue <= 507)) {maxPin = 6;} 
  else if (potValue <= 634)) {maxPin = 7;}
  else if (potValue <= 761)) {maxPin = 8;}
  else if (potValue <= 888)) {maxPin = 9;}
  else {maxPin = 10;}

This is more tuneable than the map() function above as you can decide where the 'borders' are




Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

pjfweeks

Thanks for the help! That definitely simplified my code, but sadly it did not resolve the issue with the code breaking. If the potPin input changes too rapidly or rises and falls, the code ignores the maxPin value, completes one cycle all the way to the last of the 8 LEDs, and then stops blinking altogether.

Also, I am transitioning from one led to the next without any delay, but thanks for keeping an eye out for the little details!

Grumpy_Mike

I am not sure you understood what was said before. 50K is too big a value of pot to use you should be using 10K pots. However if you give the processor time it will get the right value, so replace:-
Code: [Select]
sensorValue = analogRead(sensorPin);
  potValue = analogRead(potPin);

with
Code: [Select]
sensorValue = analogRead(sensorPin);
sensorValue = analogRead(sensorPin);
  potValue = analogRead(potPin);
  potValue = analogRead(potPin);



Go Up