For my Arduino Uno I've programmed a very simple count-down timer script for a LED ring (see code below). Instead of a fixed duration of 60 seconds, I would like to add a 4-pin dip switch with which one can set the duration:
switch #1: 30 seconds
switch #2: 60 seconds
switch #3: 120 seconds
switch #4: 300 seconds
So, for example, if switch #1 and #3 are on, the duration would be 150 seconds.
How do I wire such a dip switch and how do a get the values into my program?
#include "FastLED.h"
#define LED_PIN 6
#define NUM_LEDS 24
CRGB leds[NUM_LEDS];
unsigned long previousMillis = 0;
const long interval = 1000; // count down every 1 second (in milliseconds)
int count = 60; // start at 60 seconds
void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(2); // set brightness to 2
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV(0, 255, 255); // set all LEDs to white (0° hue, 255 saturation, 255 value)
}
FastLED.show();
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// it's been 1 second since the last count, so count down again
if (count > 0) {
count--;
leds[count] = CRGB::Black; // turn off LED
FastLED.show();
}
previousMillis = currentMillis;
}
}
An option, which gives 2^3 states:. The example sends commands to the serial command console on a Raspberry Pi in the event the Pi keyboard becomes unresponsive... a push-button reads the 3 DIP switches and performs pre-programmed code to send serial commands.
/* Pro Micro Test Code
M. Ray Burnette, published on Hackster 2017/06/13 License: MIT
ArduinoGUI: 1.6.13 on Linux Mint 17.3
Sketch uses 6,458 bytes (22%) of program storage space. Maximum is 28,672 bytes.
Global variables use 351 bytes (13%) of dynamic memory, leaving 2,209 bytes for local variables. Maximum is 2,560 bytes.
*/
#include <Streaming.h>
#include "./functions.h"
void setup()
{
pinMode(Pin1, INPUT);
digitalWrite(Pin1, HIGH); // enable pullup
pinMode(Pin2, INPUT);
digitalWrite(Pin2, HIGH); // enable pullup
pinMode(Pin4, INPUT);
digitalWrite(Pin4, HIGH); // enable pullup
pinMode(Button, INPUT);
digitalWrite(Button, HIGH); // enable pullup
Serial1.begin(115200); // This pipes to the serial TxRx
Serial.begin(9600); // USB serial, BAUD is just a placeholder
if (debugPrint) Serial << "Serial ports initialized...\n\r";
}
void loop()
{
if (! digitalRead(Button))
{
Results = nValue(); if (debugPrint) Serial << F("Results value: ") << Results << F("\n\r");
{
switch (Results)
{
case 0:
if (debugPrint) Serial << F("Case 0\n\r");
zero(); // Function to perform
delay(LoopCycleTime);
break;
case 1:
if (debugPrint) Serial << F("Case 1\n\r");
one();
delay(LoopCycleTime);
break;
case 2:
if (debugPrint) Serial << F("Case 2\n\r");
two();
delay(LoopCycleTime);
break;
case 3:
if (debugPrint) Serial << F("Case 3\n\r");
three();
delay(LoopCycleTime);
break;
case 4:
if (debugPrint) Serial << F("Case 4\n\r");
four();
delay(LoopCycleTime);
break;
case 5:
if (debugPrint) Serial << F("Case 5\n\r");
five();
delay(LoopCycleTime);
break;
case 6:
if (debugPrint) Serial << F("Case 6\n\r");
six();
delay(LoopCycleTime);
break;
case 7:
if (debugPrint) Serial << F("Case 7\n\r");
seven();
delay(LoopCycleTime);
break;
default:
if (debugPrint) Serial << F("Results value: ") << Results << F("\n\r");
delay(LoopCycleTime);
}
}
}
}
You would use your own functions here in header file
#define CommandDelay 1000 // mS
#define LoopCycleTime 1000 // mS
// Pins "7 8 9" on uC connect to encoder "1 2 4" respectively, C == Gnd
const byte Pin1 = 7; // Pin is "high" to represent 0 and "low" to represent 1
const byte Pin2 = 8; // "" ditto
const byte Pin4 = 9; // "" ditto
const byte Button = 10; // button pulls pin to Gnd to represent "press" state
boolean debugPrint = !false; // change to !false (true) to echo activity over USB port to PC
uint8_t Results = 0;
int nValue (void) { // Positive logic - 7 high, 8 high, 9 high == 7 (all Gnd == 0)
uint8_t temp = 0; // could be accomplished by masking and directly reading port
if( digitalRead( Pin4)) temp += 4;
if( digitalRead( Pin2)) temp += 2;
if( digitalRead( Pin1)) temp += 1;
return temp;
}
/*
Logic Table x == no connection(default) 0 == Grounded
2^0 2^1 2^2
Decimal /-------Pins------/ Function call
Value D7 D8 D9
0 0 0 0 zero()
1 x 0 0 one()
2 0 x 0 two()
3 x x 0 three()
4 0 0 x four()
5 x 0 x five()
6 0 x x six()
7 x x x seven()
*/
// function zero logs in as user pi with password, flushes disk queue, then reboots the RPi
void zero( void ) // called when Pins D7, D8, D9 are all low (jumpered to ground)
{
Serial1 << F("\n\r");
if(debugPrint) Serial << F("\n\r");
delay(CommandDelay);
if(debugPrint) Serial << F("Attempting to login as user Pi\n\r");
Serial1 << F("pi\n\r");
delay(CommandDelay);
Serial1 << F("raspberry\n\r");
delay(CommandDelay);
if(debugPrint) Serial << F("Attempting to write cache to SD\n\r");
Serial1 << F("sudo sync\n\r");
delay(CommandDelay);
Serial1 << F("sudo sync\n\r");
delay(CommandDelay);
if(debugPrint) Serial << F("Issuing the sudo reboot now command\n\r");
Serial1 << F("sudo reboot now\n\r");
}
// function one logs in as user pi with password, flushes disk queue, then shutdowns the RPi
void one( void )
{
Serial1 << F("\n\r");
if(debugPrint) Serial << F("\n\r");
delay(CommandDelay);
if(debugPrint) Serial << F("Attempting to login as user Pi\n\r");
Serial1 << F("pi\n\r");
delay(CommandDelay);
Serial1 << F("raspberry\n\r");
delay(CommandDelay);
if(debugPrint) Serial << F("Attempting to write cache to SD\n\r");
Serial1 << F("sudo sync\n\r");
delay(CommandDelay);
Serial1 << F("sudo sync\n\r");
delay(CommandDelay);
if(debugPrint) Serial << F("Issuing the sudo shutdown now command\n\r");
Serial1 << F("sudo shutdown now\n\r");
}
void two( void )
{
}
void three( void )
{
}
void four( void )
{
}
void five( void )
{
}
void six( void )
{
}
void seven( void )
{
}
Yes, that's right, I want to implement 15 options.
Before I can choose the best solution, I'll have to grasp the different concepts mentioned from all above contributions — it will take some time, because I'm quite a beginner!
Thanks to all contributers!
@johnerrington I don't know how to implement your code snippet in my code respectively what part it replaces in the code of the other contributions here. I would be happy if you could describe it for me.
see pins 8,9,10,11 are connected to port B as PB0, PB1, PB2, PB3
connect your switches to those pins, with the other side of each switch grounded.
in SETUP Set pins 8 - 11 as INPUT-PULLUP. eg pinMode(8, INPUT_PULLUP);
now
duration = PINB & 0b00001111;
reads ALL of portB as a binary value, and sets the 4 upper bits to zero.
so duration = 0b0000xxxx where xxxx is the value from your switches; a number in the range 0-15.
duration * = 30; //multiplies that value by 30 so duration is now 0, 30, 60, 90 ... (15*30)
I reused @paulpaulson sketch and came up with following adoptions:
// https://forum.arduino.cc/t/using-a-4-pin-dip-switch-to-set-value/1070190/2
// declare a structure of pin and interval
struct DipSwitch
{
const uint8_t pin; // the gpio
const uint16_t interval; // the interval in seconds
};
// make an array of dipswitches and initialize the values
DipSwitch dipSwitch[]
{
{A0, 30},
{A1, 60},
{A2, 120},
{A3, 300},
};
// calculate the setted interval
uint32_t getInterval()
{
const uint16_t factor = 1000; // from milliseconds to seconds
uint32_t interval = 0;
for (auto &i : dipSwitch)
if (digitalRead(i.pin) == LOW) interval += i.interval;
return interval * factor;
}
void setup()
{
Serial.begin(115200);
for (auto &i : dipSwitch)
pinMode(i.pin, INPUT_PULLUP);
Serial.println(getInterval()); // print the setted interval
}
void loop() {
Serial.println(getInterval());
delay(1000); // dirty delay just to make the output visible
}
@adamsmi, If you still have questions - ask.
If your problem is solved, mark one post as solution.
You can say thank you to helpers by pressing the heart - it will come without costs for you.
/*
ARDUINO PORT
PIN NAME
------- ----
8 PB0
9 PB1
10 PB2
11 PB3
*/
void setup() {
Serial.begin(57600);
// DDRB (R/W) pin direction (0 = INPUT / 1 = OUTPUT)
// PORTB (R/W) pin state (INPUT: 0 = LOW / 1 = HIGH | OUTPUT: 0 = PULL-UP DEACTIVATED / 1 = PULL-UP ACTIVATED)
// PINB (R) pin state (INPUT ONLY: 0 = LOW / 1 = HIGH)
DDRB &= 0x0F; //set pins 8-11 as inputs; 0x0F is 0B00001111
PORTB |= 0x0F; // set pullups on pins 8-11 as inputs
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
int interval;
// read switch value from portB
int switches = PINB & 0x0F; // 0x0F = 0B00001111 = set upper 4 bits of value to zeros.
switches ^= 0x0F; //^ is XOR: change values from lower 4 bits so 0011 becomes 1100
Serial.println(switches); //this now holds a value between 0b0000 and 0b1111 depending on the switch settings
interval = 1000 * switches;
delay(interval); //or you can use the "switches" value in your millis timing.
}