Hallo alle Miteinander ich habe folgendes problem ich möchte ein can bus system bauen mit denn ich 16 relais über 16 taster schalten möchte. Ich habe es bereits hinbekommen das ich ein relai mit einmaligen drücken an und mit einem zweiten mal drücken wieder aus schalte diess ist aber alles auf einem mega pasiert. jetzt möchte ich das schalter element nicht an der decke platzieren sondern neben die eingangs tür wärend das relais bord an der decke ist und das ganze über can bus verbinden. Leider verstehe ich trotz dieverser Videos nicht wie ich das hin bekomme das ich jedes einzelne relai über die entsprechende taste ansteuern kann. Kann mir Vlt einer helfen
Hinweis: C++ ist eine case sensitive Sprache. Du solltest also dringend Deine Shifttaste reparieren lassen, damit der Compiler Deinen Code auch verstehen kann.
Ansonsten zeige uns doch mal, was Du schon hast. Worüber willst Du den Can-Bus ansteuern?
Gruß Tommy
Danke für die schnelle Antwort
Den Cod werde ich gleich einbringen da meine freundin grade am pc sitzt. Als grund Platiene dienen mir 2 arduino mega 2560 und als can bus module 2 MCP2515 die jewals auf einen der beiden mega 2560 mit jumper kabeln verbunden sind.
zum code ich werde diesen mit nur 4 relais und 4 tasten einbringen um das ganze zu vereinfachen
Zum Testen ok, für den Dauerbetrieb solltest Du löten oder zur Not Schraubklemmen benutzen. Mit Jumper-Kabeln wirst Du nicht lange Freude daran haben.
Gruß Tommy
der "Taster-Mega" braucht nur ausschicken Taste X gedrückt
alle Teilnehmer am CANBUS - und daher auch der "Relais-Mega" kann das empfangen und braucht dann entsprechende Logik dass Bei Taste X gedrückt, das Relais y umgeschaltet wird.
int SchalterZustand1;
int SchalterZustand2;
int SchalterZustand3;
int SchalterZustand4;
int rundumLeuschtePin = 50;
int arbeitsScheinwerferRPin = 51;
int arbeitsScheinwerferLPin = 52;
int arbeitsScheinwerferHPin = 53;
int rundumLeuchtenSPin = 46;
int arbeitsScheinwerferRSPin = 47;
int arbeitsScheinwerferLSPin = 48;
int arbeitsScheinwerferHSPin = 49;
void setup(){
Serial.begin(9600);
pinMode(rundumLeuchtenSPin,INPUT);
pinMode(arbeitsScheinwerferRSPin,INPUT);
pinMode(arbeitsScheinwerferLSPin,INPUT);
pinMode(arbeitsScheinwerferHSPin,INPUT);
pinMode(rundumLeuschtePin,OUTPUT);
pinMode(arbeitsScheinwerferRPin,OUTPUT);
pinMode(arbeitsScheinwerferLPin,OUTPUT);
pinMode(arbeitsScheinwerferHPin,OUTPUT);
}
void loop(){
SchalterZustand1 = digitalRead(rundumLeuchtenSPin);
Serial.println(SchalterZustand1,DEC);
if (SchalterZustand1 >= 1)
{
digitalWrite(50,HIGH);
}
if (SchalterZustand1 <= 0)
{
digitalWrite(50,LOW);
}
SchalterZustand2 = digitalRead(arbeitsScheinwerferRSPin);
Serial.println(SchalterZustand2,DEC);
if (SchalterZustand2 >= 1)
{
digitalWrite(51,HIGH);
}
if (SchalterZustand2 <= 0)
{
digitalWrite(51,LOW);
}
SchalterZustand3 = digitalRead(arbeitsScheinwerferLSPin);
Serial.println(SchalterZustand3,DEC);
if (SchalterZustand3 >= 1)
{
digitalWrite(52,HIGH);
}
if (SchalterZustand3 <= 0)
{
digitalWrite(52,LOW);
}
SchalterZustand4 = digitalRead(arbeitsScheinwerferHSPin);
Serial.println(SchalterZustand4,DEC);
if (SchalterZustand4 >= 1)
{
digitalWrite(53,HIGH);
}
if (SchalterZustand4 <= 0)
{
digitalWrite(53,LOW);
}
}
das ist der Cod denn ich bis jetzt auf dem einem mega2560 geschrieben habe mit nur 4 tasten zur besseren verständnis. D.h. an einem mega sind die 4 tasten als auch die 4 relais angeschlossen, jetzt sollen die relais das signal über can bus von dem tasten erhalten und in denn lastzustand gehen bis das signal nochmal kommt um wieder in last freiheit zu gehen
bitte schau dir arrays an. Dann sind 4 Taster und 16 Taster exakt gleich viel Code - sogar weniger Code als das was du jetzt vervierfach hast.
Außerdem - drück mal strg-t in deiner Arduino IDE um deinen Code besser zu formatieren.
Hi @Sniperbk1172 ,
mit dem Code wirst Du aber auf Dauer nicht glücklich werden ...
- Für Jede Taste komplett separate Routinen schreiben (auch wenn per Copy&Paste vervielfältigt) wird unübersichtlich und ist sehr fehlerträchtig. (Siehe @noiasca 's Hinweis auf Arrays!).
- In der loop() ständig Relais zu schalten, mag an einem Controller noch gehen, ist aber unschön und lässt sich so nicht 1:1 auf einen Bus übertragen. Hier bietet es sich an, die Schalterzustände nur dann zu übertragen und zu schalten, wenn sich dort etwas geändert hat.
Zusatz:
SchalterZustand4 = digitalRead(arbeitsScheinwerferHSPin);
Serial.println(SchalterZustand4,DEC);
if (SchalterZustand4 >= 1)
{
digitalWrite(53,HIGH);
}
if (SchalterZustand4 <= 0)
{
digitalWrite(53,LOW);
}
Das sieht nicht nach Taster aus oder dem von Dir beschriebenen Verfahren (1. mal Tasten = EIN, 2. mal Tasten = AUS), sondern nach EIN solange der Taster gedrückt, AUS solange der Taster nicht gedrückt ist ...
int array1[16] = { 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 };
int array2[16] = { 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49 };
void setup() {
for (int i = 0; i < array2; i++) {
pinMode(array2[16], OUTPUT);
}
for (int i = 0; i < array1; i++) {
pinMode(array1[16], INPUT);
}
test();
}
void test() {
for (int i = 0; i < array2; i++) {
pinMode(array2[16], HIGH);
}
delay(200);
for (int i = 0; i < array2; i++) {
pinMode(array2[16], LOW);
}
}
void loop() {
}
meint ihr das dann so
jetzt gibst deinen Variablen noch vernünftige Namen und machst die for schleifen korrekt.
Prinzipiell der richtige Weg!
Habe mir mal erlaubt, auf die Schnelle ein Beispiel zu schreiben, das zusätzlich auch das Entprellen der Taster inkludiert (allerdings im Gegensatz zu Deiner Vorgabe mit INPUT_PULLUP, weil dann keine externen Widerstände erforderlich sind, um den Eingang auf einem festen Level zu halten, wenn der Taster offen ist):
/*
Forum: https://forum.arduino.cc/t/mit-16-tasten-16-relais-schalten-uber-can-bus-mcp2515-und-mega/1216997/8
Wokwi: https://wokwi.com/projects/388194038842918913
*/
// Diese Struktur beinhaltet alles, was für die Behandlung eines Tasters/Schalters erforderlich
// ist, das Initialisieren des Pins mit INPUT_PULLUP (so dass keine externen Widerstände erforderlich sind)
// und das Entprellen des Tasters/Schalters per Software.
// die Funktion pressed() gibt genau dann einmal(!) true zurück, wenn der Zustand des Tasters
// von HIGH auf LOW wechsel (also gerade "gedrückt wird").
//
struct schalterTyp {
byte pin;
byte state = HIGH;
byte lastState = HIGH;
unsigned long lastChange = 0;
void init(byte aPin) {
pin = aPin;
pinMode(pin, INPUT_PULLUP);
}
boolean pressed() {
byte actState = digitalRead(pin);
if (actState != lastState) {
lastChange = millis();
lastState = actState;
}
if (actState != state && millis() - lastChange > 20) {
state = actState;
return !state;
}
return false;
}
};
// Hier kann man einfach weitere Pins eingeben, der Rest der Software
// behandelt dann auch diese Pins, ohne dass etwas am Code geändert werden muss
const byte schalterPin[] = {46, 47, 48, 49};
// Die folgende Zeile berechnet, wieviele Einträge bei schalterPin[] vorhanden sind
const int schalterAnzahl = sizeof(schalterPin) / sizeof(schalterPin[0]);
// Entsprechend werden nun schalter-Struktur-Objekte angelegt
schalterTyp schalter[schalterAnzahl];
byte leuchtenZustand[schalterAnzahl];
void setup() {
Serial.begin(115200);
// Hier werden die schalter-Objekte initialisiert, indem ihnen der zugehörige Pin
// zugewiesen wird.
for (int i = 0; i < schalterAnzahl; i++) {
schalter[i].init(schalterPin[i]);
leuchtenZustand[i] = LOW; // Alle Leuchten werden hier mal auf LOW gesetzt.
}
}
void loop() {
// In der loop() werden alle Taster schnell nacheinander ausgelesen.
for (int i = 0; i < schalterAnzahl; i++) {
if (schalter[i].pressed()){
leuchtenZustand[i] = !leuchtenZustand[i];
Serial.print("Leuchte Nr. ");
Serial.print(i+1);
Serial.print(" ist ");
Serial.println((leuchtenZustand[i] == HIGH) ? "EIN" : "AUS");
};
}
}
Kannst Du auf Wokwi ausprobieren und dort auch selbst weiterentwickeln!
Viel Erfolg!
Ok vielen Dank bis hierher an alle aber wie kann ich jetzt anhand deines beispiel des jewaligen taster in meinem fall sind die taster von 18-33 einen OUTPUT 34-49 zuordnen das wenn ich taste 18 drücke relai 34 geschaltet wird und mit taste 19 relai 35 usw
Nun, am einfachsten, indem Du die Ausgabe Pins in gleicher Reihenfolge wie die Schalterpins in ein Array schreibst. Dann schaltet schalter[i] die leuchte[i].
Du brauchst sowieso zwei getrennte Arrays, da die Taster an einem und die Relais an einem anderen Controller angeschlossen sein werden, wenn Du die Schalterzustände per CANBus überträgst.
Also damit ich das verstehen das was du im beispiel geschrieben hast ist die tasten eingabe D.h ich muss das nur noch mit can bus hinterlegen und auf der empfänger seite das gleiche nur mit den relais
Klingt sicher etwas einfacher, als es ist, aber das kann man so sagen.
Auf der Sendeseite kannst Du bei Änderung den Zustand aller "Leuchten"-Zustände übertragen. Das geht bei 16 Leuchten mit 2 Byte (1 Bit pro Leuchte).
Auf der Empfangsseite übernimmt man diese beiden Byte und prüft Bit für Bit, ob sich der Zustand geändert hat. Dort wo aus 0 eine 1 oder aus 1 eine 0 geworden ist, merkt man sich den neuen Zustand und schaltet das jeweilige Relais ein (bei einer 1) oder aus (bei einer 0).
Also
- Byte = B00000000 => schaltet die Leuchten 0 ... 7
(Reihenfolge der Bits 7 6 5 4 3 2 1 0) - Byte = B00000000 => schaltet die Leuchten 8 ... 15
Reihenfolge der Bits 15 14 13 12 11 10 9 8)
Das Setzen und Abfragen der Bits kann man hartkodiert selbst machen oder man benutzt die bei Arduino vorbereiteten binären Funktionen dazu:
Guckst Du hier: https://www.arduino.cc/reference/de/
Soweit ok?
Du kannst es gerne auch auf Wokwi probieren, allerdings leider nicht mit zwei Controllern, aber das Prozedere kann man auch auf einem Controller beispielhaft entwickeln, indem man die Daten per 2 Byte an eine weitere Funktion übergibt, die dann die Relais schaltet. Das reicht eigentlich zunächst mit 4 Schaltern/Relais. Wenn man es richtig aufsetzt, ist es leicht auf mehrere Schalter/Relais erweiterbar.
Ich nehme an, dass Du es erst einmal selbst versuchen willst ...
Gruß
ec2021
Alternativ zu #18 kann man auch die CAN-Bus-ID zur Auswahl des Relais verwenden. Dazu wird der Index Teil der ID. In den Daten übergibt man die Information für "an" oder "aus".
Siehe auch MCP_CAN Library for Arduino.
Stimmt, hier eröffnen sich viele Möglichkeiten:
- Binäre Codierung des Relaiszustands (wie bei #18 beschrieben)
- Adressierung der einzelnen Relais über verschiedene CANID und Status im Datenteil der Message
- Definition eines Kommandos zum Übergeben von Relaisnummer und gewünschtem Status
canMsg.data[0] = Kommando
canMsg.data[1] = Nr. des Relais
canMsg.data[2] = Zustand des Relais (HIGH oder LOW) - Definition eines Kommandos zum Übergeben einer Pinnummer und des gewünschtem Status
canMsg.data[0] = Kommando
canMsg.data[1] = Pinnummer
canMsg.data[2] = Zustand des Pins (HIGH oder LOW) - ... usw.
Die Übergabe einer Pinnummer hätte sogar den Charme, dass man die Software des Controllers, der die Relais direkt ansteuert, bei Erweiterung nicht anpassen muss.
Auch eine Abfrage des Status aller oder einzelner Leuchten mit Ausgabe über z.B. eine LCD-Anzeige ist zusätzlich denkbar.
Eine sehr schöne Aufgabe ....
Hier noch ein Tipp, falls Du nie mehr als eine Taste zur Zeit betätigen willst: