Problem with dipswitches using an ATMEGA328

Hi all,

I've got a project where i'm selecting 4 channels using 2 dipswitches. I breadboarded it using two slider switches and it worked great. However, i've had PCB's made and now only one of the channels work correctly.

All the hardware is definitely connected correctly was just wondering if there's something in the code stopping it from working as it did on the breadboard with the arduino uno.

I'll post the few lines from the full code for the dipswitches. Any help would be very much appreciated!

const byte dipSwitchPins[] = {4, 5};  // Pins for dip switches

void setup() {

pinMode(dipSwitchPins[0], INPUT_PULLUP);  // Dip switch 1
pinMode(dipSwitchPins[1], INPUT_PULLUP);  // Dip switch 2

}

void loop() {

 // Read dip switches to set MIDI channel
  byte dipSwitchState = digitalRead(dipSwitchPins[0]) | (digitalRead(dipSwitchPins[1]) << 1);
  channelNo = map(dipSwitchState, 0, 3, 1, 2);

}

Does that mean you used your Ohmmeter to verify the connection to the Arduino and verify the switches turn on and off? How are they wired? One pin to ground and the other to an Arduino pin?

I don't know what the sketch should do, so I don't know what is wrong with it.

A few notes:

  1. The sketch does not compile.
  2. The digitalRead() function returns HIGH or LOW. You may not use that together with a bitwise "or". You may not shift it.
  3. Mapping a integer value from 0...3 to 1...2 does not make sense. Please use normal code.
  4. I'm almost certain that your hardware has a problem.

You should stay out of trouble, by writing normal and clean code. Don't try to outsmart yourself. Don't try to put a few things into a single line. Always follow the KISS rule: https://en.wikipedia.org/wiki/KISS_principle

Can you show the complete sketch ?

Can you show a schematic and a photo of your project. The first question we will ask is: "where are the decoupling capacitors ?".

Try the code in Wokwi simulation: Problem with dipswitches using an ATMEGA328 - Wokwi ESP32, STM32, Arduino Simulator

1 Like

Yeah sorry I should've been more specific, it's a PCB with the ATMEGA328 in a dip socket. I've tested everything with a multimeter and it all checks out, 2 of the pins to 4 and 5 and then the other 2 are going to ground.

I didn't paste the whole sketch because it's long and not much of it is relevant to the dip switches but sure here's the full code. Rest of the project works perfectly it's just literally these dip switches that are giving me jip and the way I see it they should be fairly straight forward.

#include "Toggle.h"
#include <MIDI.h>
 
MIDI_CREATE_DEFAULT_INSTANCE();

const byte LEDs[] = {15, 14, 16, 10, 9, 8, 7, 6}; // Pins for LEDs
const byte dipSwitchPins[] = {4, 5};  // Pins for dip switches

static int progNo = 0;
static byte channelNo = 1;  // Default MIDI channel
  
const byte b1Pin = 2;
const byte b2Pin = 3;
Toggle b1, b2;
 
const uint16_t deltaT = 850; // ms after that duration, a pressed button is considered in long press state
 
enum SystemState : byte {
  B1R_B2R, B1P_B2R, B1L_B2R,
  B1R_B2P, B1P_B2P, B1L_B2P,
  B1R_B2L, B1P_B2L, B1L_B2L
} state = B1R_B2R;
 
const char* stateDescriptor[] = {
  "B1R_B2R", "B1P_B2R", "B1L_B2R",
  "B1R_B2P", "B1P_B2P", "B1L_B2P",
  "B1R_B2L", "B1P_B2L", "B1L_B2L"
};
 
void manageState() {
  static SystemState previousState = B1R_B2R;
 
  switch (state) {
    case B1R_B2R:
      b1.poll();
      if (b1.onPress()) {
        b1.clearTimer();
        state = B1P_B2R;
      } else {
        b2.poll();
        if (b2.onPress()) {
          b2.clearTimer();
          state = B1R_B2P;
        }
      }
      break;
 
    case B1R_B2P:
      b1.poll();
      if (b1.onPress()) {
        b1.clearTimer();
        state = B1P_B2P;
      } else {
        b2.poll();
        if (b2.onRelease()) {
          state = B1R_B2R;
          progNo--; // Decrement program change
      if (progNo < 0) progNo = 7; // Wrap around to 7
      MIDI.sendProgramChange(byte(progNo), channelNo);
        } else {
          if (b2.pressedFor(deltaT)) {
            state = B1R_B2L;
      MIDI.sendControlChange(19, 2, channelNo);
          }
        }
      }
      break;
 
    case B1R_B2L:
      b1.poll();
      if (b1.onPress()) {
        b1.clearTimer();
        state = B1P_B2L;
      } else {
        b2.poll();
        if (b2.onRelease()) {
          state = B1R_B2R;
      MIDI.sendControlChange(19, 3, channelNo);
        }
      }
      break;
 
    case B1P_B2R:
      b1.poll();
      if (b1.onRelease()) {
        state = B1R_B2R;
        progNo++; // Increment program change
       if (progNo > 7) progNo = 0; // Wrap around to 0
      MIDI.sendProgramChange(byte(progNo), channelNo);
      } else {
        b2.poll();
        if (b2.onPress()) {
          b2.clearTimer();
          state = B1P_B2P;
          }
        else if (b1.pressedFor(deltaT)) {
          state = B1L_B2R;
      MIDI.sendControlChange(19, 1, channelNo); 
        }
      }
      break;
 
    case B1P_B2P:
  {
    unsigned long releaseTime = millis(); // Record the time when the first button is released
      b1.poll();
      if (b1.onRelease()) {
        state = B1R_B2R;
      MIDI.sendControlChange(41, 127, channelNo);
      MIDI.sendControlChange(49, 127, channelNo);
      } else {
             b2.poll();
      if (b2.onRelease()) {
        // Check if the second button is released within a short time after the first one
        if ((millis() - releaseTime) < 700) {
          state = B1R_B2P; // Buttons released within the time window
      MIDI.sendControlChange(41, 127, channelNo);
      MIDI.sendControlChange(49, 0, channelNo);
        } else {
          if ((millis() - releaseTime) < 700) {
          state = B1P_B2R; // Second button released, treat as separate releases
      MIDI.sendControlChange(41, 127, channelNo);
      MIDI.sendControlChange(49, 0, channelNo);
        }
        }
      }else if (b1.pressedFor(deltaT)) {
          state = B1L_B2P;
      MIDI.sendControlChange(46, 127, channelNo);
        }
        else if (b2.pressedFor(deltaT)) {
          state = B1P_B2L;
      MIDI.sendControlChange(46, 127, channelNo);
        }
      }
  }
      break;
 
    case B1P_B2L:
      b1.poll();
      if (b1.onRelease()) {
        state = B1R_B2L;
      } else {
        b2.poll();
        if (b2.onRelease()) {
          state = B1P_B2R;
        }
        else if (b1.pressedFor(deltaT)) {
          state = B1L_B2L;
        }
      }
      break;
 
    case B1L_B2R:
      b1.poll();
      if (b1.onRelease()) {
        state = B1R_B2R;
     MIDI.sendControlChange(19, 3, channelNo);
      } else {
        b2.poll();
        if (b2.onPress()) {
          b2.clearTimer();
          state = B1L_B2P;
        }
      }
      break;
 
    case B1L_B2P:
      b1.poll();
      if (b1.onRelease()) {
        state = B1R_B2P;
      } else {
        b2.poll();
        if (b2.onRelease()) {
          state = B1L_B2R;
        }
        else if (b2.pressedFor(deltaT)) {
          state = B1L_B2L;
        }
      }
      break;
 
    case B1L_B2L:
      b1.poll();
      if (b1.onRelease()) {
        state = B1R_B2R;
        MIDI.sendControlChange(46, 0, channelNo);
      } else {
        b2.poll();
        if (b2.onRelease()) {
        state = B1R_B2R;
        MIDI.sendControlChange(46, 0, channelNo);
        }
      }
      break;
  }

  // Update LEDs and print program and channel number
  for (byte i = 0; i < 8; i++) digitalWrite(LEDs[i], progNo != i ? LOW : HIGH);

  // Read dip switches to set MIDI channel
  byte dipSwitchState = digitalRead(dipSwitchPins[0]) | (digitalRead(dipSwitchPins[1]) << 1);
  channelNo = map(dipSwitchState, 0, 3, 1, 2);
 
}
 
void setup() {
  MIDI.begin(MIDI_CHANNEL_OMNI);
  b1.begin(b1Pin);
  b2.begin(b2Pin);
  pinMode(dipSwitchPins[0], INPUT_PULLUP);  // Dip switch 1
  pinMode(dipSwitchPins[1], INPUT_PULLUP);  // Dip switch 2
  for (byte i = 0; i < 8; i++) pinMode(LEDs[i], OUTPUT);
}
 
void loop() {
  manageState();

}

Not what the code you posted shows!

Alright, that is not too bad.
Which Arduino board do you use ? I see pin numbers up to 16.

Beside what I wrote before, there is one thing that catches my attention: the Toggle.poll() for the buttons.

I assume that the Toggle.poll() is like a "update" function. That means you have to call that every time the loop() runs. Always.

Then you can check in the switch-case the Toggle.onPress() and Toggle.onRelease(). If the Toggle library is any good, then multiple Toggle.poll() has no influence on the Toggle.onPress() and Toggle.onRelease().

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.