Bin neu hier und auch im arduino.
Ich überlege, mir einen zu zu legen, um ein Projekt zu realisieren.
Folgendes möchte ich am ende haben:
16 LEDS(bzw 32, aber 2 sollen immer parallel leuchten) die jeweils über einen ihnen zugeordneten Taster eingeschaltet werden.
Dabei sollen je 8 paare aus je einer grüne und roten LED bestehen, wobei sich die jeweils die passende grüne LED ausschalten soll, wenn die rote aktiv wird und umgekehrt.
Meine Fragen dazu sind:
ist sowas sinnvoll realisierbar mit dem arduino oder gibts da ne kostengünstigere analoge schaltung?
wenn realisierbar... welchen arduino empfehlt ihr und was brauch ich evtl noch dazu, da ich ja am ende 16 Eingänge und 16 ausgänge brauche?
das ist für einen Microcontroller kein Problem.
Wenn du das "Analog" machen willst, wäre die Frage, wie gut deine Kenntnisse mit "Analogen" Bauteilen ist.
du müsstest noch definieren, wodurch so ein LED-Pärchen dann wieder umgeschaltet werden soll.
Noch besser ist - du beschreibst was du eigentlich genau machen willst. Weil so ein Taster und eine LED ... das kann ja nicht der eigentliche Zweck sein. Sonst könntest ja auch einfache Schalter nehmen.
an deiner Stelle würde ich mit einem Arduino UNO R3 anfangen. Machst halt am Anfang nur 5 Ausgänge/5 Eingänge.
Wenn du mehr brauchst
du kannst die zweite "inverse" LED an den gleichen Ausgang hängen
du kannst LEDs per Multiplex ansteuern (irgendwer wird jetzt noch Charlieplexing ergänzen)
du kannst LED Treiber verwenden
du kannst addressiebare LEDs verwenden (Stichwort Neopixel, WS2811, APA106)
du kannst deine Tasten in einer Matrix verschalten
Ich möchte bei einem Dartturnier an der Turnierleitung visuell anzeigen, welche boards gerade belegt sind, und welche gerade frei sind, um die nächsten Paarungen entsprechend einzuteilen.
Grün für Board ist frei, rot für Board ist belegt.
Warum nicht Leuchtmittel und Schalter? Warum ein µC? Was versprichst Du Dir davon?
An dieser Stelle möchte ich WS2815 (12 V mit weniger Strom) ergänzen, wobei das bei den wenigen Pixeln eher eine Randnotiz ist
Grundsätzlich stellt sich die Frage nach der notwendigen Helligkeit der Leuchtmittel. Ich habe noch nie ein Dartturnier gesehen, aber wenn es mutmaßlich in einer hell erleuchteten Turnhalle stattfindet, benötigst Du eine genügend hohe Aufmerksamkeitswirkung. Möglicherweise benötigst Du helle LEDs mit mehr Strombedarf. Weil Arduinos nur recht wenig Strom an den Pins vertragen, braucht es eine "Verstärkerschaltung". Dazu eignen sich Relais genauso wie Leistungselektronik mit Transistoren.
Weil LED-Streifen so schön einfach zu handhaben sind, könnten auch mehrere Pixel eines Streifens einen Lichtpunkt rot/grün bilden, also 2x2, 3x3 oder 4x4. Anstelle von Streifen sind auch Pixel-Ketten mit 12 mm Durchmesser denkbar. Bei Interesse einfach fragen. (Die Links dienen nur der Anschauung!)
/*
LEDs toggled with buttons
https://forum.arduino.cc/t/einstieg-arduino/1333397/2
2024-12-18 by noiasca
code not in thread
*/
#include "button.h"
class Led {
private:
const uint8_t pin; // the GPIO
boolean isActive = false; // ob diese LED grundsätzlich grad aktiv ist oder nicht
public:
Led (uint8_t pin) : pin(pin) {}
void begin() {
pinMode(pin, OUTPUT);
}
void toggle() {
if (isActive) {
digitalWrite(pin, LOW);
}
else {
digitalWrite(pin, HIGH);
}
isActive = !isActive;
}
};
Led leds[] {8, 9, 10, 11};
constexpr size_t noOfLeds = sizeof(leds) / sizeof(leds[0]);
Button buttons[noOfLeds] {A0, A1, A2, A3};
void setup() {
Serial.begin(115200);
Serial.println("Startup");
for (size_t i = 0; i < noOfLeds; i++) {
leds[i].begin();
buttons[i].begin();
}
}
void loop() {
for (size_t i = 0; i < noOfLeds; i++) {
if (buttons[i].wasPressed()) leds[i].toggle();
}
}
//
button.h
/*
a class to debounce a button
the program is based on "state change detection" and converted to OOP to make it reusable
2024-11-09 by noiasca
*/
class Button { // a simple class for buttons based on the "Debounce" example
const uint8_t buttonPin; // the GPIO / pin for the button
static constexpr byte debounceDelay = 30; // the debounce time; Static because we only need one value for all buttons
const bool active; // is the pin active HIGH or active LOW (will also activate the pullups!)
bool lastButtonState = HIGH; // the previous reading from the input pin
uint32_t lastDebounceTime = 0; // the last time the output pin was toggled
public:
/**
\brief constructor for a button
The constructor takes the GPIO as parameter.
If you omit the second parameter, the class will activate the internal pullup resistor
and the button should connect to GND.
If you set the second parameter to HIGH, the button is active HIGH.
The button should connect to VCC.
The internal pullups will not be used but you will need an external pulldown resistor.
\param buttonPin the GPIO for the button
\param active LOW (default) - if button connects to GND, HIGH if button connects to VCC
*/
Button(uint8_t buttonPin, bool active = LOW) : buttonPin(buttonPin), active(active) {}
/**
\brief set the pin to the proper state
Call this function in your setup().
The pinMode will be set according to your constructor.
*/
void begin() {
if (active == LOW)
pinMode(buttonPin, INPUT_PULLUP);
else
pinMode(buttonPin, INPUT);
}
/**
\brief indicate if button was pressed since last call
@return HIGH if button was pressed since last call - debounce
*/
bool wasPressed() {
bool buttonState = LOW; // for the current reading from the input pin
byte reading = LOW; // "translated" state of button LOW = released, HIGH = pressed, despite the electrical state of the input pint
if (digitalRead(buttonPin) == active) reading = HIGH; // overwrite the current button state (independent from active LOW or active HIGH)
if ((millis() - lastDebounceTime) > debounceDelay) { // If the switch changed, AFTER any pressing or noise
if (reading != lastButtonState && lastButtonState == LOW) { // If there was a change and and last state was LOW (= released)
buttonState = HIGH;
}
lastDebounceTime = millis();
lastButtonState = reading;
}
return buttonState;
}
};
//
Vielleicht nicht die schönste Lösung, aber schnell aus einer vorhandenen abgeleitet:
/*
Forum: https://forum.arduino.cc/t/einstieg-arduino/1333397/4?u=ec2021
Wokwi: https://wokwi.com/projects/417649916925208577
Matrix keyboard for 4 rows x 4 columns = 16 keys
requires one Pin per row and one per column = 8 pins in this case
And a 16 pixel Neopixel ring
Press the red key to start a game
Press the button that corresponds to the blue pixel (changes the color to green)
If a "black pixel" button was pressed the black pixel changes to red
If all blue pixels have been changed to green the game ends and
can be restarted with the red button
2024/03/25 by ec2021
Modified for "Dart Board Occupancy Display"
2024/12/18 by ec2021
*/
#include <Adafruit_NeoPixel.h>
#define PIN_NEO_PIXEL 8 // Arduino pin that connects to NeoPixel
#define NUM_PIXELS 16 // The number of LEDs (pixels) on NeoPixel
Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800);
byte pixelColReference[NUM_PIXELS];
const byte clBlack = 0;
const byte clGreen = 1;
const byte clRed = 2;
// key matrix
int row[] = {2, 3, 4, 5};
int column[] = {13, 12, 11, 10};
int col_scan;
int last_scan = -1;
constexpr int noOfRows = sizeof(row) / sizeof(row[0]);
constexpr int noOfColumns = sizeof(column) / sizeof(column[0]);
boolean blueModus = false;
int greenPixels = 0;
int redPixels = 0;
void setup()
{
Serial.begin(115200);
NeoPixel.begin();
NeoPixel.clear();
for (int i = 0; i < noOfRows; i++)
{
//Initialization of row pins
pinMode(row[i], OUTPUT);
}
for (int i = 0; i < noOfColumns; i++)
{
//Initialization of column pins
pinMode(column[i], INPUT);
digitalWrite(column[i], HIGH);
}
setAllTo(clBlack);
delay(1000);
setAllTo(clGreen);
delay(1000);
setAllTo(clRed);
}
int aRow;
int aColumn;
void loop()
{
if (buttonPressed(aRow, aColumn)) {
action(aRow, aColumn);
}
}
void setAllTo(byte aColor) {
for (int i = 0; i < NUM_PIXELS; i++) {
pixelColReference[i] = aColor;
}
updateNeoPixels();
}
void updateNeoPixels() {
for (int pixel = 0; pixel < NUM_PIXELS; pixel++) {
switch (pixelColReference[pixel]) {
case clBlack: NeoPixel.setPixelColor(pixel, NeoPixel.Color(0, 0, 0));
break;
case clGreen : NeoPixel.setPixelColor(pixel, NeoPixel.Color(0, 255, 0));
break;
case clRed: NeoPixel.setPixelColor(pixel, NeoPixel.Color(255, 0, 0));
break;
}
}
NeoPixel.show();
}
boolean buttonPressed(int &aRow, int &aColumn) {
//Check for pressed buttons
static boolean pressed = false;
static unsigned long lastPressTime = 0;
if (pressed && millis() - lastPressTime < 300) { // The 300 ms avoid bouncing and
// quick key repetitions
return false;
}
pressed = false;
for (int i = 0; i < noOfRows; i++)
{
if (pressed) break;
for (int j = 0; j < noOfRows; j++) {
digitalWrite(row[j], HIGH);
}
digitalWrite(row[i], LOW);
for (int j = 0; j < noOfColumns; j++)
{
col_scan = digitalRead(column[j]);
if (col_scan == LOW)
{
lastPressTime = millis();
pressed = true;
aRow = i;
aColumn = j;
break;
}
}
}
return pressed;
}
void action(int i, int j)
{
int keyNo = i * noOfColumns + j + 1;
switch (keyNo) {
case 1 ... NUM_PIXELS :
changeColor(keyNo - 1);
break;
default: // and all others here ...
Serial.println("No action implemented yet ....");
}
}
void changeColor(byte pixel) {
byte color = pixelColReference[pixel];
switch (color) {
case clRed: color = clGreen;
break;
case clGreen: color = clRed;
break;
}
pixelColReference[pixel] = color;
updateNeoPixels();
}
Voraussetzung für die simple Matrixauswertung ist, dass man nicht mehr als eine Taste gleichzeitig betätigt. Sollte aber hier kein Problem darstellen.
Die Led-Anzahl kann einfach erweitert werden; jedoch würde man (anders als im Online-Simulator) die Led-Streifen auf separat mit Strom versorgen.
Ich habe (weil in meiner Grundlage vorhanden) eine kreisförmige Anordnung genutzt. Die verwendeten digital ansteuerbaren Leds gibt es in Streifenform. Wichtig: Es muss sich um einen ''digitalen" Ledstreifen handeln! Dort ist i.d.R. eine Beschriftung mit GND, D0, DI und Vcc aufgedruckt. Ist dort neben GND auf dem Streifen noch R,G und B zu lesen, können die Leds nicht einzeln sondern nur zusammen angesteuert werden.
Hier gibt es ggf. weitere Erläuterungen zum Thema (nicht von mir im Detail geprüft ...):
Der User geht zur Tafel, legt den passenden Schalter um, und die LED wird umgeschaltet.
Fertig ist.
Die Alternative wäre (richtig schön aufwendig).
Man mache das ganze über eine Software auf einen PC.
Da kann man dann die Spieler eintragen, eine Scheibe zuweisen, und durch den Eintrag des Ergebnis die LED umstellen. (Wobei die LED dann nicht mal eine LED sein muss)
Das würde sogar ohne LEDS funktionieren, wenn man ein PC nimmt, der 2 Monitore anklemmen kann.