In over my head, need opinions.

So, I'm writing this program, the primary function of which is switching on one of six outputs based on the data from four I/O lines from the host.

So far, my attempts have failed utterly, either because I can't program (Entirely possible.) or due to unrelated issues. (Such as hardware problems.)

Given that I have no earthly idea what I'm doing, I figured a good place to start would be to see if I was even going in the right direction with the program.

Here's how the hardware works: There are four data lines. The first one, ELCLOCK, pulses high when a switch is requested. At that same time, the other three pins, ELD0, ELD1, and ELD2 pulse what output to turn on.

eld0 eld1 eld2 Result
LOW LOW LOW output1
HIGH LOW LOW output2
LOW HIGH LOW output3
HIGH HIGH LOW output4
LOW LOW HIGH output5
HIGH LOW HIGH output6

I had an interrupt attached to the input for ELCLOCK, so when it went high, the following would happen:

  // Read state of eldata pins
  if (digitalRead(eld2) == HIGH)
  {
    switchValue = 1;
  }
  else
  {
    switchValue = 0;
  }
  if (digitalRead(eld1) == HIGH)
  {
    switchValue += 2;
  }
  if (digitalRead(eld0) == HIGH)
  {
    switchValue += 4;
  }
  
  // Switch on panel determined by above function
  switch(switchValue) {
  case 0:
    digitalWrite(panel1, HIGH);
    break;
  case 1:
    digitalWrite(panel5, HIGH);
    break;
  case 2:
    digitalWrite(panel3, HIGH);
    break;
  case 4:
    digitalWrite(panel2, HIGH);
    break;
  case 5:
    digitalWrite(panel6, HIGH);
    break;
  case 6:
    digitalWrite(panel4, HIGH);
    break;
  default:
    digitalWrite(panel1, HIGH);
  }

I had it printing switchValue to the serial port for debugging, and besides the fact that the interrupts would happen constantly with or without input, it was returning 7.

So, before I take this any further, is this right at all or am I completely on the wrong track with this? I've tried debugging it, but on the off chance that this is one of those occasions where I have the right idea but it's failing because of some stupid error I can't spot, I don't want keep tearing up the code. (Like when you spend a whole day debugging and rewriting a PHP file, only to find out it was failing because of some misplaced whitespace somewhere...)

How's it all wired, do have pull-ups, what is the interrupt condition, why don't you post the sketch...?

So many questions.

Hi there

Have a look at the last post in this thread:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1273613567/9

You need to read the input values and based on the conditional logic set the outputs - caseswitch is your friend here :smiley:

-Fletcher

I have the internal pull-up resistors enabled on the data lines, which is a point of confusion for me. The original circuit that this is supposed to replace, which was based around 7400 series logic ICs, had a pull-up resistor network on the input pins, without which the lines wouldn't actually go HIGH when pulsed, they'd just go from LOW to floating. The internal pull-ups should behave the same way as an external one, right? That doesn't seem to be the case though, because it seems like the pull-up resistors are what's causing everything to read HIGH. (Well DUH.)

All I know is that no matter what I do, it fails spectacularly. Inputs pulled high, this happens. (I also tried an external pull-up RN, same thing.) Inputs pulled low, it freaks out with random pulses on every pin. (The same as if I didn't pull them at all) I've tried every possible mode for the interrupt, and I've tried INT0 and INT1.

The reason I didn't post the sketch is because I keep rewriting everything else, and that's the part I needed to know whether or not I was going in the right direction with. But here you go:

// Data Inputs
int elclock = 2;      // Strobes HIGH to indicate a switch is requested
int eld0 = 3;            // First of three pins that determines which panel to switch
int eld1 = 4;
int eld2 = 5;

// Other Inputs
int potPin = 0;            // Brightness adjustment potentiometer

// Outputs
int pwm = 6;            // MOSFET connecting panels to ground, apply PWM for brightness control
int panel1 = 7;            // First of six MOSFET outputs for supplying power to the panels
int panel2 = 8;
int panel3 = 9;
int panel4 = 10;
int panel5 = 11;
int panel6 = 12;

// Debug LED
int led = 13;            // Strobes during interrupt (For testing purposes on Arduino board)

// Values
int potValue = 0;      // Analog read value of the brightness pot, gets divided to determine PWM value
int switchValue = 0;      // Result of interrupt switching algorithm, determines panel to switch

void setup() {
  pinMode(elclock, INPUT);
  pinMode(eld0, INPUT);
  pinMode(eld1, INPUT);
  pinMode(eld2, INPUT);
  pinMode(potPin, INPUT);
  pinMode(panel1, OUTPUT);
  pinMode(panel2, OUTPUT);
  pinMode(panel3, OUTPUT);
  pinMode(panel4, OUTPUT);
  pinMode(panel5, OUTPUT);
  pinMode(panel6, OUTPUT);
  pinMode(pwm, OUTPUT);
  
  // Enable internal pullup resistors
  digitalWrite(elclock, HIGH);
  digitalWrite(eld0, HIGH);
  digitalWrite(eld1, HIGH);
  digitalWrite(eld2, HIGH);
  
  // Enable the interrupt
  attachInterrupt(0, switchpanel, RISING);
  
  // Turn on the first panel by default
  digitalWrite(panel1, HIGH);
  
  // Enable serial for debugging
  Serial.begin(9600);
}

void loop() {
  // Read the brightness pot and apply PWM
  potValue = analogRead(potPin);
  analogWrite(pwm, potValue/4);  
}

void switchpanel() {
  // Flash debug LED to indicate interrupt
  digitalWrite(led, HIGH);
  
  // Turn off all panels
  digitalWrite(panel1, LOW);
  digitalWrite(panel2, LOW);
  digitalWrite(panel3, LOW);
  digitalWrite(panel4, LOW);
  digitalWrite(panel5, LOW);
  digitalWrite(panel6, LOW);
  
  // Read state of eldata pins

  if (digitalRead(eld2) == HIGH)
  {
    switchValue = 1;
  }
  else
  {
    switchValue = 0;
  }
  if (digitalRead(eld1) == HIGH)
  {
    switchValue += 2;
  }
  if (digitalRead(eld0) == HIGH)
  {
    switchValue += 4;
  }
  
  // Switch on panel determined by above function
  switch(switchValue) {
  case 0:
    digitalWrite(panel1, HIGH);
    break;
  case 1:
    digitalWrite(panel5, HIGH);
    break;
  case 2:
    digitalWrite(panel3, HIGH);
    break;
  case 4:
    digitalWrite(panel2, HIGH);
    break;
  case 5:
    digitalWrite(panel6, HIGH);
    break;
  case 6:
    digitalWrite(panel4, HIGH);
    break;
  default:
    digitalWrite(panel1, HIGH);
  }
  // Print value to serial for debugging, turn off debug LED
  Serial.println(switchValue);
  digitalWrite(led, LOW);
}

My logic probe shows that the inputs are LOW, regardless of what the Arduino seems to think is going on, so I'm sort of at a loss.

Have a look at the last post in this thread:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1273613567/9

You need to read the input values and based on the conditional logic set the outputs - caseswitch is your friend here

-Fletcher

Hey, that sure looks like what I want this to be doing, didn't know it could be done in such a straightforward way. :slight_smile:

Okay, I'll give it a rewrite using that instead, and see if that fixes anything!

Holy crap it works. I didn't think the problem was 100% the code, but it was... I thought there was some sort of input noise problem too. Man, there's no way I could have debugged that. :-[

Thanks for the help guys, and extra thanks for the code, Fletcher. :smiley:

// Data Inputs
int elclock = 2;      // Strobes HIGH to indicate a switch is requested
int eld0 = 3;            // First of three pins that determines which panel to switch
int eld1 = 4;
int eld2 = 5;

// Other Inputs
int potPin = 0;            // Brightness adjustment potentiometer

// Outputs
int pwm = 6;            // MOSFET connecting panels to ground, apply PWM for brightness control
int panel1 = 7;            // First of six MOSFET outputs for supplying power to the panels
int panel2 = 8;
int panel3 = 9;
int panel4 = 10;
int panel5 = 11;
int panel6 = 12;

// Values
int potValue = 0;      // Analog read value of the brightness pot, gets divided to determine PWM value
int switchValue = 0;      // Result of interrupt switching algorithm, determines panel to switch

int val1 = 0;
int val2 = 0;
int val3 = 0;

byte caseStep = 0;
byte caseStep2 = 0;

void setup() {
  pinMode(elclock, INPUT);
  pinMode(eld0, INPUT);
  pinMode(eld1, INPUT);
  pinMode(eld2, INPUT);
  pinMode(potPin, INPUT);
  pinMode(panel1, OUTPUT);
  pinMode(panel2, OUTPUT);
  pinMode(panel3, OUTPUT);
  pinMode(panel4, OUTPUT);
  pinMode(panel5, OUTPUT);
  pinMode(panel6, OUTPUT);
  pinMode(pwm, OUTPUT);
  
  // Enable internal pullup resistors
  digitalWrite(elclock, HIGH);
  digitalWrite(eld0, HIGH);
  digitalWrite(eld1, HIGH);
  digitalWrite(eld2, HIGH);
  
  // Enable the interrupt
  attachInterrupt(0, switchpanel, RISING);
  
  // Turn on the first panel by default
  digitalWrite(panel1, HIGH);
 }

 void loop(){
   // Read the brightness pot and apply PWM
  potValue = analogRead(potPin);
  analogWrite(pwm, potValue/4);
 }
 
 void switchpanel() {
  detachInterrupt(0); // disable the interrupt
  caseStep = 0; // set caseStep to default value
  
  // Read eld0..2 inputs
  val1 = digitalRead(eld0);
  val2 = digitalRead(eld1);
  val3 = digitalRead(eld2);
  
  // Logical conditions:
  if ((val1 == LOW)  and (val2 == LOW) and (val3 == LOW)) caseStep = 1;
  if ((val1 == HIGH)  and (val2 == LOW) and (val3 == LOW)) caseStep = 2;
  if ((val1 == LOW)  and (val2 == HIGH) and (val3 == LOW)) caseStep = 3;
  if ((val1 == HIGH)  and (val2 == HIGH) and (val3 == LOW)) caseStep = 4;
  if ((val1 == LOW)  and (val2 == LOW) and (val3 == HIGH)) caseStep = 5;
  if ((val1 == HIGH)  and (val2 == LOW) and (val3 == HIGH)) caseStep = 6;


  // Turn all panels off
  digitalWrite(panel1, LOW);
  digitalWrite(panel2, LOW);
  digitalWrite(panel3, LOW);
  digitalWrite(panel4, LOW);
  digitalWrite(panel5, LOW);
  digitalWrite(panel6, LOW);

  // Switch on selected panel
  switch (caseStep) {
    case 0: //default settings
      digitalWrite(panel1, HIGH);
      break;

    case 1:
      digitalWrite(panel1, HIGH);
      break;

    case 2:
      digitalWrite(panel2, HIGH);
      break;

    case 3:
      digitalWrite(panel3, HIGH);
      break;

    case 4:
      digitalWrite(panel4, HIGH);
      break;
    
    case 5:
      digitalWrite(panel5, HIGH);
      break;

    case 6:
      digitalWrite(panel6, HIGH);
      break;
  }
  attachInterrupt(0, switchpanel, RISING); // re-enable interrupt
}

I'll have to append a link to my project once it's finished. ;D

Congratulations on getting something working!

Seems to me your use of switch statements overly complicate the code which can be simplified to:

// Data Inputs
const int elclock   =  2;   // Strobes HIGH to indicate a switch is requested

const int eld0      =  3;   // First of three pins that determines which panel to switch
const int eld1      =  4;
const int eld2      =  5;

// Other Inputs
const int potPin    =  0;   // Brightness adjustment potentiometer

// Outputs
const int pwm       =  6;   // MOSFET connecting panels to ground, apply PWM for brightness control

const int panel1    =  7;   // First of six MOSFET outputs for supplying power to the panels
const int panel2    =  8;
const int panel3    =  9;
const int panel4    = 10;
const int panel5    = 11;
const int panel6    = 12;

void switchpanel()
{
    detachInterrupt(0); // disable the interrupt

// Read eld0..2 inputs
    int iSwitch = 0;
    iSwitch |= ((HIGH == digitalRead(eld2)) ? 1 : 0);   iSwitch <<= 1;
    iSwitch |= ((HIGH == digitalRead(eld1)) ? 1 : 0);   iSwitch <<= 1;
    iSwitch |= ((HIGH == digitalRead(eld0)) ? 1 : 0);

// Turn all panels off
    digitalWrite(panel1, LOW);
    digitalWrite(panel2, LOW);
    digitalWrite(panel3, LOW);
    digitalWrite(panel4, LOW);
    digitalWrite(panel5, LOW);
    digitalWrite(panel6, LOW);

// Logical conditions:
    switch ( iSwitch )
    {
        case 0: digitalWrite(panel1, HIGH); break;
        case 1: digitalWrite(panel2, HIGH); break;
        case 2: digitalWrite(panel3, HIGH); break;
        case 3: digitalWrite(panel4, HIGH); break;
        case 4: digitalWrite(panel5, HIGH); break;
        case 5: digitalWrite(panel6, HIGH); break;
    }
    
    attachInterrupt(0, switchpanel, RISING); // re-enable interrupt
}

void loop()
{
    // Read the brightness pot and apply PWM
    analogWrite(pwm, analogRead(potPin) / 4);
}

void setup()
{
    pinMode(elclock, INPUT);

    pinMode(eld0, INPUT);
    pinMode(eld1, INPUT);
    pinMode(eld2, INPUT);

    pinMode(potPin, INPUT);

    pinMode(panel1, OUTPUT);
    pinMode(panel2, OUTPUT);
    pinMode(panel3, OUTPUT);
    pinMode(panel4, OUTPUT);
    pinMode(panel5, OUTPUT);
    pinMode(panel6, OUTPUT);

    pinMode(pwm, OUTPUT);

// Enable internal pullup resistors
    digitalWrite(elclock, HIGH);

    digitalWrite(eld0, HIGH);
    digitalWrite(eld1, HIGH);
    digitalWrite(eld2, HIGH);

// Enable the interrupt
    attachInterrupt(0, switchpanel, RISING);

// Turn on the first panel by default
    digitalWrite(panel1, HIGH);
}

Seems to me your use of "if" "switch" statements overly complicate the code, which could be simplified by a few arrays.

I agree. But then we'd need to "introduce" structures. Where to stop, where to begin?

Beyond arrays, no "structures" are needed, the program is shorter (fewer dark corners for the bugs to hide), compiles to fewer bytes, and the superfluous/incorrect function calls commented-out.

[Compiled but untested]

// Data Inputs
const byte elclock   =  2;   // Strobes HIGH to indicate a switch is requested

const byte eld [3]   =  {3, 4, 5};

// Other Inputs
const byte potPin    =  0;   // Brightness adjustment potentiometer

// Outputs
const byte pwm       =  6;   // MOSFET connecting panels to ground, apply PWM for brightness control

const byte panel []  =  {7, 8, 9, 10, 11, 12};

#define SIZEOF(x) (sizeof(x)/ sizeof(x[0]))

void switchpanel()
{
  detachInterrupt(0); // disable the interrupt

  int iSwitch = digitalRead (eld[2]) << 2 | digitalRead (eld[1]) << 1 | digitalRead (eld[0]);

  // Turn all panels off
  for (int i = 0; i < SIZEOF(panel); ++i) {
    digitalWrite(panel [i], LOW);
  }

  if (iSwitch < SIZEOF(panel)) {
    digitalWrite (panel [iSwitch], HIGH);
  }

  attachInterrupt(0, switchpanel, RISING); // re-enable interrupt
}

void loop()
{
    // Read the brightness pot and apply PWM
    analogWrite(pwm, analogRead(potPin) / 4);
}

void setup()
{
  pinMode(elclock, INPUT);
  digitalWrite(elclock, HIGH);

  for (int i = 0; i < SIZEOF (eld); ++i) {
    pinMode(eld [i], INPUT);
    digitalWrite(eld[i], HIGH);
  }

  // pinMode(potPin, INPUT);  // Bzzzt! I don't think so!
  // pinMode(pwm, OUTPUT);  // not required

  for (int i = 0; i < SIZEOF (panel); ++i) {
    pinMode(panel [i], OUTPUT);
  }

  // Enable the interrupt
  attachInterrupt(0, switchpanel, RISING);

  // Turn on the first panel by default
  digitalWrite(panel [0], HIGH);
}