Go Down

Topic: A strange issue with digitalWrite (Read 177 times) previous topic - next topic

wsender

I'm having a strange problem with digitalWrite. I have some writes that are not occurring that are immediately before another write. See the code below (this is on an Uno R3):


Code: [Select]

#include <EEPROM.h>

enum ACTIVE_OUTPUT_STATES {NONE, INPUT0, INPUT1, INPUT2};
enum POWER_STATES {ON, OFF};

const int EEPAddress = 50;

const int PixelData = 2;
const int PowerSW = 3;
const int PowerLED = 4;
const int PowerEnable = 19;
const int Input0SW = 5;
const int Input0LED = 6;
const int Input1SW = 7;
const int Input1LED = 8;
const int Input2SW = 9;
const int Input2LED = 10;
const int Input0Enable = 11;
const int Input1Enable = 12;
const int Input2Enable = 13;

const int debounceTime = 80;  //ms
const int messageTime = 1000; //ms
const int timeoutTime = 250; //ms

int OutputMemory;
int LastMessage = 0;
int x = 4;


ACTIVE_OUTPUT_STATES ActiveOutput = NONE;
POWER_STATES Power = OFF;

void setup() {
  // assign pinmodes

  Serial.begin(9600);



  pinMode(PixelData, OUTPUT);

  pinMode(PowerSW, INPUT);
  pinMode(PowerLED, OUTPUT);
  pinMode(PowerEnable, OUTPUT);

  pinMode(Input0SW, INPUT);
  pinMode(Input0LED, OUTPUT);
  pinMode(Input0Enable, OUTPUT);

  pinMode(Input1SW, INPUT);
  pinMode(Input1LED, OUTPUT);
  pinMode(Input1Enable, OUTPUT);

  pinMode(Input2SW, INPUT);
  pinMode(Input2LED, OUTPUT);
  pinMode(Input2Enable, OUTPUT);

  //set initial states of outputs;
  digitalWrite(PowerLED, LOW);
  //setting PowerLED high for debug purposes, this shoudl be changed to LOW before release
  digitalWrite(PowerEnable, LOW);
  digitalWrite(Input0LED, LOW);
  digitalWrite(Input0Enable, LOW);
  digitalWrite(Input1LED, LOW);
  digitalWrite(Input1Enable, LOW);
  digitalWrite(Input2LED, LOW);
  digitalWrite(Input2Enable, LOW);
  // initialize state machines


  Serial.println("Setup Complete\n\n");
}

void loop() {
  //
  //  digitalWrite(PowerEnable, LOW);
  //  delay(1000);
  //  digitalWrite(PowerEnable, HIGH);
  //  delay(1000);
  switch (Power)
  {
    case OFF:
      if (!digitalRead(PowerSW)) {
        x = debounce(PowerSW);
        if (x) {
          Serial.println("Power On\n");
          digitalWrite(PowerEnable, HIGH);
          digitalWrite(PowerLED, HIGH);
          Power = ON;
        }
      }
      break;
    case ON:
      if (!digitalRead(PowerSW)) {
        x = debounce(PowerSW);
        if (x) {
          Power = OFF;
          Serial.println("Power Off\n");
          digitalWrite(PowerEnable, LOW);
          digitalWrite(PowerLED, LOW);
        }
      }
      break;
    default:
      Serial.println("Power Error \n\n");
      Power = OFF;
      break;
  }

I have an LED hooked up to PowerLED and PowerEnable is hooked up to the gate of a FET. Currently the state changes are working and when I push the button (PowerSW) the LED turns off and on as expected. However, the PowerEnable writes aren't occurring.

As a sanity check I wrote a little PowerEnable toggle (you can see it commented out at the top of loop()) and that works so I know the HW is ok. Does anyone know why the PowerEnable digitalWrite isn't working?

aarg

Please post the entire sketch, for one thing so we can see what 'debounce()' does.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

Erik_Baas

* Is anything connected to pin 28?
* Are you using I2C?

wsender

The only thing connected to pin 28 is that GPIO output. I2C is not being used.

Here's the entire sketch:
Code: [Select]

#include <EEPROM.h>

enum ACTIVE_OUTPUT_STATES {NONE, INPUT0, INPUT1, INPUT2};
enum POWER_STATES {ON, OFF};

const int EEPAddress = 50;

const int PixelData = 2;
const int PowerSW = 3;
const int PowerLED = 4;
const int PowerEnable = 19;
const int Input0SW = 5;
const int Input0LED = 6;
const int Input1SW = 7;
const int Input1LED = 8;
const int Input2SW = 9;
const int Input2LED = 10;
const int Input0Enable = 11;
const int Input1Enable = 12;
const int Input2Enable = 13;

const int debounceTime = 80;  //ms
const int messageTime = 1000; //ms
const int timeoutTime = 250; //ms

int OutputMemory;
int LastMessage = 0;
int x = 4;


ACTIVE_OUTPUT_STATES ActiveOutput = NONE;
POWER_STATES Power = OFF;

void setup() {
  // assign pinmodes

  Serial.begin(9600);



  pinMode(PixelData, OUTPUT);

  pinMode(PowerSW, INPUT);
  pinMode(PowerLED, OUTPUT);
  pinMode(PowerEnable, OUTPUT);

  pinMode(Input0SW, INPUT);
  pinMode(Input0LED, OUTPUT);
  pinMode(Input0Enable, OUTPUT);

  pinMode(Input1SW, INPUT);
  pinMode(Input1LED, OUTPUT);
  pinMode(Input1Enable, OUTPUT);

  pinMode(Input2SW, INPUT);
  pinMode(Input2LED, OUTPUT);
  pinMode(Input2Enable, OUTPUT);

  //set initial states of outputs;
  digitalWrite(PowerLED, LOW);
  //setting PowerLED high for debug purposes, this shoudl be changed to LOW before release
  digitalWrite(PowerEnable, LOW);
  digitalWrite(Input0LED, LOW);
  digitalWrite(Input0Enable, LOW);
  digitalWrite(Input1LED, LOW);
  digitalWrite(Input1Enable, LOW);
  digitalWrite(Input2LED, LOW);
  digitalWrite(Input2Enable, LOW);
  // initialize state machines


  Serial.println("Setup Complete\n\n");
}

void loop() {
  //
  //  digitalWrite(PowerEnable, LOW);
  //  delay(1000);
  //  digitalWrite(PowerEnable, HIGH);
  //  delay(1000);
  switch (Power)
  {
    case OFF:
      if (!digitalRead(PowerSW)) {
        x = debounce(PowerSW);
        if (x) {
          Serial.println("Power On\n");
          digitalWrite(PowerEnable, HIGH);
          digitalWrite(PowerLED, HIGH);
          Power = ON;
        }
      }
      break;
    case ON:
      if (!digitalRead(PowerSW)) {
        x = debounce(PowerSW);
        if (x) {
          Power = OFF;
          Serial.println("Power Off\n");
          digitalWrite(PowerEnable, LOW);
          digitalWrite(PowerLED, LOW);
        }
      }
      break;
    default:
      Serial.println("Power Error \n\n");
      Power = OFF;
      break;
  }
  //  switch(ActiveOutput)
  //  {
  //    case NONE:
  //      Serial.println("No Output\n");
  //      if(digitalRead(Input0Enable) == LOW){
  // Serial.println("Output 0 Active\n");
  //        ActiveOutput = INPUT0;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      else if(digitalRead(Input1Enable) == LOW){
  // Serial.println("Output 1 Active\n");
  //        ActiveOutput = INPUT1;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      else if(digitalRead(Input2Enable) == LOW){
  //        Serial.println("Output 2 Active\n");
  // ActiveOutput = INPUT2;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      break;
  //   case INPUT0:
  //      Serial.println("Output 0 Active\n");
  //      digitalWrite(Input0Enable, HIGH);
  //      digitalWrite(Input0LED, HIGH);
  //      if(digitalRead(Input1Enable) == LOW){
  // Serial.println("Output 1 Active\n");
  //        ActiveOutput = INPUT1;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      else if(digitalRead(Input2Enable) == LOW){
  // Serial.println("Output 2 Active\n");
  //        ActiveOutput = INPUT2;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      break;
  //   case INPUT1:
  //      Serial.println("Output 1 Active\n");
  //      digitalWrite(Input1Enable, HIGH);
  //      digitalWrite(Input1LED, HIGH);
  //      if(digitalRead(Input0Enable) == LOW){
  //        ActiveOutput = INPUT0;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      else if(digitalRead(Input2Enable) == LOW){
  //        ActiveOutput = INPUT2;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      break;
  //   case INPUT2:
  //      Serial.println("Output 2 Active\n");
  //      digitalWrite(Input2Enable, HIGH);
  //      digitalWrite(Input2LED, HIGH);
  //      if(digitalRead(Input0Enable) == LOW){
  //        ActiveOutput = INPUT0;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      else if(digitalRead(Input1Enable) == LOW){
  //        ActiveOutput = INPUT1;
  //        EEPROM.write(EEPAddress, ActiveOutput);
  //      }
  //      break;
  //   default:
  //      Serial.println("Active Output Error\n");
  //      ActiveOutput = NONE;
  //      break;
  //  }
}




int debounce(int buttonPin) {
  int buttonState = 0;
  int initialTime = millis();
  int pushTime = millis();

  while (1) {
    buttonState = digitalRead(buttonPin);
    if (buttonState && ((millis() - pushTime) > debounceTime)) {
      return 1;
    }
    if (buttonState && ((millis() - initialTime) > timeoutTime)) {
      return 0;
    }
  }
}

aarg

This function can never respond to the timeout value. It will always return a 1 because 'debounceTime' and 'timeoutTime' are both constants and debounceTime will always be reached first.

Code: [Select]

const int debounceTime = 80;  //ms
const int messageTime = 1000; //ms
const int timeoutTime = 250; //ms
...

int debounce(int buttonPin) {
  int buttonState = 0;
  int initialTime = millis();
  int pushTime = millis();

  while (1) {
    buttonState = digitalRead(buttonPin);
    if (buttonState && ((millis() - pushTime) > debounceTime)) {
      return 1;
    }
    if (buttonState && ((millis() - initialTime) > timeoutTime)) {
      return 0;
    }
  }
}
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

wsender

That is true about the issues in debounce() but how does that affect the digitalWrite in loop()

jremington

#6
Nov 22, 2020, 03:43 am Last Edit: Nov 22, 2020, 03:43 am by jremington
Which pin corresponds to digital output number 19 on an Arduino Uno R3?
Code: [Select]
const int PowerEnable = 19;

wsender


david_2018

Which pin corresponds to digital output number 19 on an Arduino Uno R3?
Code: [Select]
const int PowerEnable = 19;
A5/SCL

wsender

19 = A5/SCL = physical pin 28.

As stated earlier if I load a simple toggle of PowerEnable the HW behaves as expected. The problem seems to be related to the code I posted above.

wsender

It appears I've fixed it by adding a small delay after the serial write. See below:
Code: [Select]

  switch (Power)
  {
    case OFF:
      if (!digitalRead(PowerSW)) {
        x = debounce(PowerSW);
        if (x) {
          Serial.println("Power On\n");
          delay(50);
          digitalWrite(PowerEnable, HIGH);
          digitalWrite(PowerLED, HIGH);
          Power = ON;
        }
      }
      break;
    case ON:
      if (!digitalRead(PowerSW)) {
        x = debounce(PowerSW);
        if (x) {
          Power = OFF;
          Serial.println("Power Off\n");
          delay(50);
          digitalWrite(PowerEnable, LOW);
          digitalWrite(PowerLED, LOW);
        }
      }
      break;
    default:
      Serial.println("Power Error \n\n");
      Power = OFF;
      break;
  }


Does anyone know why this works?

johnwasser

It appears I've fixed it by adding a small delay after the serial write.

Does anyone know why this works?
My guess would be that your 'debounce' function is not working and the power is being turned off immediately after it is turned on.  Try instead, replacing the 'debounce' function with a 'delay(50);'.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp
See who has no social life: https://forum.arduino.cc/index.php?action=stats :)

david_2018

#12
Nov 22, 2020, 04:37 pm Last Edit: Nov 22, 2020, 04:42 pm by david_2018
Can you modify your simple toggle sketch to toggle both PowerEnable and PowerLED?  If PowerLED is toggling correctly with your full sketch, I don't see why PowerEnable would not also be toggling, which leaves the possibility that there is something wrong with the hardware.  I would also comment out the #include statement for EEPROM.h, although that should not be using I2C unless you have a library installed for external EEPROM that uses the same filename.

<edit> posted before I read your post about the sketch working after adding a delay()

david_2018

Code: [Select]

int debounce(int buttonPin) {
  int buttonState = 0;
  int initialTime = millis();
  int pushTime = millis();



Ah, declare initialTime and pushTime as unsigned long, not int.

Go Up