7 changes to 0 on only 1 BCD switch

I had a problem with the keypad library last week, on a remote control I am making,so I took the 4 pushbuttons straight to 4 pins on the chip, which works fine.

I have 7 BCD switches, which I scan in sequence, read the 1,2,4,8 switch outputs ( through diodes ) and convert to byte to send.

All is well except one of the switches shows all numbers fine, except 7, which shows as a 0.

I couldnt imagine any software problem doing this, so I just changed the switch, and its still doing it . ( the message [7] is the one that is mixed up )

I swapped the pins E and F over in the code, and its another switch that has the problem, but message 7 will not show a 7.

I have monitired the messages as they are generated, and message [7] will show 0 when it should be 7.

I have measured with a meter, and I get continuity between the 1,2,4 outputs of the BCD switch to the chip.

The code is below, can anybody spot my error ?

uses 100 k pull down resistors on BCD inputs to chip, diodes anodes to switch 1248 outputs. 
 Uses 3 x AA 3v battery
#include <VirtualWire.h>    // Wireless transmitter/receiver library
#include <avr/sleep.h>      // powerdown library
#include <avr/interrupt.h>  // interrupts library

// ***********************************************************************

uint8_t SW[4]; // assign four data pins from bcd switches

int SW0 = 5;               // bits to read from bcd switches LSB
int SW1 = 6;               
int SW2 = 7;               
int SW3 = 8;               // - MSB
int address = 0;          
int add0;  //  bits generated from cd switches
int add1;
int add2;
int add3;
int key;
int comA = 14;   // switch scans to swithch sliders
int comB = 4;
int comC = 10;
int comD = 15;
int comE = 3; 
int comF = 11;
int comG = 12;

int PIN = 77;  //  preset pin number to send  

int dataB;
int dataC;
int dataD;
int dataE;
int dataF;
int dataG;

int pause=HIGH;

int dpin0 = 0;              // apparently redefined by Serial as Serial Monitor works
int dpin1 = 1;              // apparently redefined by Serial as Serial Monitor works
int pin2 = 2;               // Int0 interrupt pin

// ***********************************************************************

int sleep_count = 0;      // flag/counter to tell us to go sleep

// ***********************************************************************
// create an array to store data to be sent out
char msg [9]; //  pin, key, A,B,C,D,E,F,G    

int runbut= 16;
int updatebut = 17;
int setbut = 18;
int pausebut = 19;

// *  Name:        pin2Interrupt, "ISR" to run when interrupted in Sleep Mode
void pin2Interrupt()
  /* This brings us back from sleep. */
// *  Name:        enterSleep
void enterSleep()
  /* Setup pin2 as an interrupt and attach handler. */
  attachInterrupt(0, pin2Interrupt, FALLING);
  delay(50); // need this?
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // setting up for sleep ...
  sleep_enable();                       // setting up for sleep ...
  ADCSRA &= ~(1 << ADEN);
  PRR = 0xFF;
  sleep_mode();                         // now goes to Sleep and waits for the interrupt
  /* The program will continue from here after the interrupt. */
  detachInterrupt(0);                 //disable interrupts while we get ready to read the keypad 
  PRR = 0x00;
  /* First thing to do is disable sleep. */


//**************************************************************************  LOOP
void setup()
  /* Setup the pin directions, write inputs High to turn on internal pullups */
  pinMode(pin2, INPUT);                 // our sleep interrupt pin
  digitalWrite(pin2, HIGH);  // set pull up res
  // define all the unused pins as inputs with internal pullups for lower power state
  pinMode(dpin0, INPUT);                  // apparently redefined by Serial as Serial Monitor works (receiving anyway)
  digitalWrite(dpin0, HIGH);              // apparently redefined by Serial as Serial Monitor works
  pinMode(dpin1, INPUT);                  // apparently redefined by Serial as Serial Monitor works
  digitalWrite(dpin1, HIGH);              // apparently redefined by Serial as Serial Monitor works

  pinMode (comA , OUTPUT );  // common slders of the BCD switches
  pinMode (comB , OUTPUT );
  pinMode (comC , OUTPUT );
  pinMode (comD , OUTPUT );
  pinMode (comE , OUTPUT );
  pinMode (comF , OUTPUT );
  pinMode (comG , OUTPUT );

  pinMode(SW0, INPUT); // LSB of bcd
  byte add0 = 0; 
  pinMode(SW1, INPUT); // LSB+1
  byte add1= 0;
  pinMode(SW2, INPUT);  // LSB+2
  byte add2 = 0;
  pinMode(SW3, INPUT);  // MSB of bcd
  byte add3 = 0;

  // PIN = 18; //  ( preset for WPCC to 1101  ( 13 )  Pin number  SACS = 11  Glenwoodrugby 18
  Serial.println("my address is: ");
  digitalWrite(SW0, LOW);   //  disable pullups on PIN inputs to save current, finished with these pins PIN read.msg[0]
  digitalWrite(SW1, LOW);
  digitalWrite(SW2, LOW);
  digitalWrite(SW3, LOW);

  Serial.println("TX setup");              // for debug only 
  // vw_set_rx_pin(0);
  vw_set_tx_pin(9);    //  Tx module connections and speed
  vw_set_ptt_pin(13); // powers Tx and LED
  ;	                      // Bits per sec - had to double from 2000 with 8MHz 3.3V Pro-Mini
  //  VW reset it to input as the Rx default pin.
  // pinMode (comA , OUTPUT );  // common slders of the BCD switches
  pinMode ( runbut, INPUT );
  pinMode ( setbut, INPUT );
  pinMode ( updatebut, INPUT );
  pinMode ( pausebut, INPUT );
  digitalWrite(runbut, HIGH); 
  digitalWrite(setbut, HIGH); 
  digitalWrite(updatebut, HIGH);  
  digitalWrite(pausebut, HIGH);  

// *************************************************************************end of void Setup()  


second part

void loop()

  Serial.println("Sleep");               // for debug only

  enterSleep();                             // call Sleep function to put us out
  //  THE PROGRAM CONTINUEs FROM HERE after waking up in enterSleep()
  int runstate = digitalRead(runbut); 
  if ( runstate == 0 ) { 
    key = 65 ;
  int pausestate = digitalRead(pausebut); 
  if ( pausestate == 0 ) { 
    key = 67 ;
  int updatestate = digitalRead(updatebut); 
  if ( updatestate == 0 ) { 
    key = 66 ;
  int setstate = digitalRead(setbut); 
  if ( setstate == 0 ) { 
    key = 68 ;
  Serial.print("key read =");   
  // {
  msg [0]  = PIN;
  msg [1]  = key;

  digitalWrite(comA, LOW);    //  make sure all commons low
  digitalWrite(comB, LOW);
  digitalWrite(comC, LOW);
  digitalWrite(comD, LOW);
  digitalWrite(comE, LOW);
  digitalWrite(comF, LOW);
  digitalWrite(comG, LOW);
  //******************************  NOW TAKE EACH COM HIGH AND READ THE SWITCHES

  digitalWrite(comA, HIGH);  
  scan ();

  msg [2]  = address;

  digitalWrite(comA, LOW);       
  digitalWrite(comB, HIGH);
  scan ();
  msg [3]  = address;
  digitalWrite(comB, LOW);      
  digitalWrite(comC, HIGH);
  msg [4]  = address;
  digitalWrite(comC, LOW);        
  digitalWrite(comD, HIGH);
  msg [5]  = address;
  digitalWrite(comD, LOW);        
  digitalWrite(comE, HIGH);
  msg [6]  = address;

  digitalWrite(comE, LOW);    
  digitalWrite(comF, HIGH);
  scan () ;
  msg [7]  = address;

  digitalWrite(comF, LOW);        
  digitalWrite(comG, HIGH);
  scan () ;
  msg [8]  = address;
  digitalWrite(comG, LOW);    

  Serial.print("  msg0 = ");      
  Serial.println( int (msg[0])   );
  Serial.print("  msg1 = ");      
  Serial.println(int (msg[1] )  );
  Serial.print("  msg2 = ");      
  Serial.println(int (msg[2] )  );
  Serial.print("  msg3 = ");      
  Serial.println(int (msg[3] )  );
  Serial.print("  msg4 = ");      
  Serial.println(int (msg[4] )  );
  Serial.print("  msg5 = ");      
  Serial.println(int (msg[5] )  );
  Serial.print("  msg6 = ");      
  Serial.println(int (msg[6] )  );
  Serial.print("  msg7 = ");      
  Serial.println(int (msg[7] )  );
  Serial.print("  msg8 = ");      
  Serial.println(int (msg[8] )  );
  Serial.print("  msg9 = ");      
  Serial.println(int (msg[9] )  );

  vw_send((uint8_t *)msg, 9);     // send the character out
  vw_wait_tx();                             // Wait until the whole message is gone
  delay (10 ); // leaves gap between transmissions
  //    Serial.println("sent once");
  vw_send((uint8_t *)msg, 9   );     // send the character out
  vw_wait_tx();                             // Wait until the whole message is gone

  //  } //                                           // end of if(key) & transmitting a character

} // end of void loop  
void scan ()  {

  add3 = digitalRead(SW3); 
  add3 = add3 << 3;
  add2 = digitalRead(SW2);
  add2 = add2 << 2;
  add1 = digitalRead(SW1);
  add1 = add1 << 1;
  add0 = digitalRead(SW0);
  address = address|add3;
  address = address|add2;
  address = address|add1;
  address = address|add0; 


Hi boffin1,

I read through the code but didn't spot anything.

What do you see on serial monitor? Does 7 appear as 0 there also?

I suggest you start a new test sketch and copy over to that only the minimum code to scan the bcd switches and print them to serial. Leave out all the code for the other switches, all the virtual wire and sleep stuff, so you can eliminate them from your enquiries. If you still get the issue, post your test sketch.


Thanks Paul,

Yes the Serial monitor shows 0 too.

As you say I will try a minimum scan and see what happens.

Hi, can you post a copy of your circuit, either CAD or picture of hand drawn circuit in jpg, png or pdf format.
A picture of your project as well, how are you constructing this, using protoboard?

Tom........ :slight_smile:

Hi Tom

I will post some pics when I get it finished.

The display ( a scroreboard ) is all pcbs, but the remote is a wiring mess until I can find some sockets to fit the BCD switches. The chips is on a little pcb.

I will post some pics when I get it finished.

I think Tom meant post pics so we can help you check for wiring errors, not to admire your finished handiwork! (Which will be very admirable, I'm sure, once its actually working)

Right,, the wiring is OK, this one only has seven BCD switches, you should see the one I did recently with 19 BCD switches.

I have made loads of these, and never had trouble with keypad or the scanning.

I will whittle the code down a bit later and see what is happenning.

Hi, can you write a simple program that just reads the BCD outputs and you manually connect the active to the appropriate BCD switch.
Have you got diodes in series with each BCD output to isolate each bank, don't forget, when you activate one BCD switch, the deactivated ones are not open circuit, the arduino output is pulling them LOW, so if any other of the switches is selecting anything but zero, that BCD output will be pulled down. Also, if one other non activated BCD switches has say 3 displayed then outputs 1 and 2 will be shorted together in the switch.

Tom... :slight_smile:
ps its hard to describe but I can diagram it for you if you like.

Heres a circuit of a simple 6 digit version, if there are more digits I use daisychained CD4017s to sequence them all, with just 6 pins of the micro.
As you can see each switch has 4 diodes on it.

Hi, got to be "ghosts in the machine" ,I Robot.
The other BCD switches prove that the arduino inputs work, the outputs are working cos you can read all the BCDs, just one BCD position doesn't read 7, thats 1,2,4 switched in.
Looks like you will have to do a simple program, but manually apply the BCD select voltage.

Tom... :slight_smile:

You swap the pin allocations for E and F in the code, and the apparent fault moves in the output. That indicates the problem is in the switch.

Presumably the same thing happens if you swap the "common" wires to each switches.

The problem is in the switch. It has a defect in the rotor pattern such that a hole (or debris) in the conductor moves under the common wiper in the "7" position only.

You said you tested the 1, 2 and 4 wires, but I suspect you did not test them with the switch in the "7" position. Oh, hang on - you tested the wires between the switch and the chip - not the switch itself. You need to test it using the meter in the "diode check" position.

When I switched the E and F scans, a completely different switch now wont send the 7.

I though it was the switch obviously, as the other numbers were fine, so that with its diodes was the first thing I changed.

I will have another look later, I have 4 things to get finished this weekend !

sometime during debugging another hassle, I commented out line 2 here

Serial.println("TX setup"); // for debug only
// vw_set_rx_pin(0);
vw_set_tx_pin(9); // Tx module connections and speed
vw_set_ptt_pin(13); // powers Tx and LED

I must have added that at some previous time when I had a problem, but uncommenting solved it.

default pin for rx even if you are only using a transmittter is 11, and I am using that to scan F, so I guess the VW makes it an input.

Thanks for your time guys.