hulp arduino can bus

Beste,ik zou graag 18 schakelaars aan de ene arduino en 18 leds aan de andere arduino en dat verbinden met can bus.Ik gebruik de MCP2515,TJA1050 can bus module.Het lukt mij tot 8 schakelaars te bedienen maar meer lukt mij niet.Een stuk uit de code zender

In het voorbeeld worden telkens 8 bytes verzonden, dat zijn dus 54 bits ! Zou ruimschoots moeten volstaan om 18 schakelaars te verzenden, dit zijn dus maar 18 bits (een schakelaar is aan of uit).
Je moet dus de code aanpassen daar waar de toestand van de schakelaars in de buffer[] stmp worden gecodeerd. Toestand van de eerste 8 schakelaars komen dus in de stmp[0], de volgende 8 komen in stmp[1] en dan nog 2 in stmp[2]. Bij de ontvanger natuurlijk ook aanpassen.

Je mag maar 8 bytes versturen dat is meer dan genoeg voor 18 schakelaars (18 bits)

Sterker: jij verstuurt daar een bericht per schakelaar dus je zou zelfs met 1 byte overweg kunnen. Of 5 bits!

Duss alles tegelijk versturen benodigd wat bit codering, dat is even doorbijten: pseudo code:

If switch1 stmp[0]=1 // eerste byte en bit
If switch2 stmp[0]+=2 // tweede bit
If switch3 stmp[0]+=4
If switch4 stmp[0]+=8
If switch5 stmp[0]+=16 // vijfde bit
If switch6 stmp[0]+=32
If switch7 stmp[0]+=64
If switch8 stmp[0]+=128 // achtste bit

If switch9 stmp[1]=1 // de volgende byte
If switch10 stmp[1]+=2
If switch11 stmp[1]+=4
...
If switch17 stmp[2]=1
.....
CAN.sendMsgBuf(0x70,0, 8, stmp);
// 8 bytes worden verstuurt, overbodig maar zo is het compatible met je voorbeeld code...
// x+=16 betekend hetzelfde als x=x+16
// 1 = bit 1
// 2 = bit 2
// 4 = bit 3
// 8 = bit 4
// een byte met de waarde 27 betekend dus
// 16 + 8 + 2 + 1 : schakelaar 5,4,2 en 1 aan en de rest uit
// 255 : alle 8 schakelaars aan
// 192 : schakelaars 7 en 8 aan de rest uit
// et cetera

Per schakelaar is wat minder decodeerwerk maar meer berichten op de lijn en langzamer: zoals je voorbeeld nu is:

If switch7 CAN.sendMsgBuf(0x70,0, 1, 7);
If switch8 CAN.sendMsgBuf(0x70,0, 1, 8);
If switch18 CAN.sendMsgBuf(0x70,0, 1, 18);
Etc

Letop ik verstuur nu maar 1 byte, zie de 1 in Send opdracht.

Je hoeft ook niet elke keer LOW en HIGH door te sturen... geen HIGH is LOW, we zijn niet van de werkverschaffing;) gewoon elke keer alle leds uitzetten en aanzetten wat je ontvangt.

Decoderen mag je zelf uitpluizen. ;)

Tip:
If buf[0] & 16 digitalwrite(D5,HIGH)

If buf[1] & 128 digitalwrite(D16,HIGH)

succes!

Ik doe dit voor mijn hobby en nieuw met arduino, ik moet nog veel leren,dus alle hulp is welkom!Doe ik het dan zo voor s2

Op die manier verstuur je voor elke switch een bericht. Niet nodig.

Je bouwt eerst je 3 bytes op : stmp[0] stmp[1] en stmp[2]. En op het laatst verstuur je de hele rits met 1 Send commando.

Je wil natuurlijk niet de canbus elke 25ms bezetten met 8 bytes per schakelaar.

[Bericht gewijzigd door K7Jz op 20 januari 2019 14:43:19 (61%)]

Ok,ik ga dit morgen eens testen,bedankt!

Ik heb zelf geen arduino omgeving dus ik geef wat tips op de gok:

c code:



unsigned char stmp[8];

if (swstate1 == HIGH)
  {
    stmp[0] += B00000001;

}
if (swstate2 == HIGH)
  {
    stmp[0] += B00000010; //bit2 van links, de decimale waarde is 2

}

if (swstate3 == HIGH)
  {
    stmp[0] += B00000100;  //bit3 van links, de decimale waarde is 4

}


if (swstate4 == HIGH)
  {
    stmp[0] += B00001000;  //bit4 van links, de decimale waarde is 8

}

.......

if (swstate18 == HIGH)
  {
    stmp[2] += B00000010;  //bit 18 van links, de decimale waarde is 2 van de derde byte (stmp[2])

}

CAN.sendMsgBuf(0x70,0, 3, stmp);  
// we versturen nu 18 schakelaars in één bericht in 3 bytes... heel efficient.
delay(200);  
// delay kan wel wat langer, we hebben de delay nu niet 18 keer maar 1 keer.

c code:



  unsigned char len = 3; // we gebruiken nog maar 3 bytes.
  unsigned char buf[3]; // hier ook 3 bytes.
  int a =0;
  char b =0; 
 
    if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
    {
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
         rxId= CAN.getCanId();
        Serial.println("-----------------------------");
        Serial.println("get data from ID: ");
        Serial.println(rxId);
 
        for(int i = 0; i<len; i++)    // print the data
        {

            Serial.print(buf[i],BIN); // We gaan lekker binair bekijken, 
            Serial.print("\t");
        }

  if ( buf[0] & B00000001 ){ // is de eerste bit van buf[0] 1??
    digitalWrite(D1,HIGH);
  } else { 
    digitalWrite(D1,LOW);    // als die bit 0 was dan zetten we hem uit.. 
  }


  if ( buf[0] & B00000010 ){ //is de tweede bit van buf[0] 1??
    digitalWrite(D2,HIGH);
  } else { 
    digitalWrite(D2,LOW);
  }

  if ( buf[0] & B00000100 ){  //derde bit
    digitalWrite(D3,HIGH);
  } else { 
    digitalWrite(D3,LOW);
  }
..........

  if ( buf[2] & B00000010 ){ //18e bit, 2e bit van 3e byte.
    digitalWrite(D18,HIGH);
  } else { 
    digitalWrite(D18,LOW);
  }

....

Ik kan hier niet zelf compileren dus er kan een typefout/denkfout of iets in zitten.

Nog veel stoerder en netter is als je de 18 pins in een for loop uitleest

c code:

int myPinArray[18]={D1,D2,D3,D4,D5,.......D18};

long msg=0; // een long is 4 bytes, 18 bits passen dus.

for (int i=0; i<18; i++) { 

  swstate = DigitalRead(myPinArray[i]);
  
  if (swstate == HIGH) { msg += 1 << i ; }
  
  //  1 << i betekend zoiets als 2 tot de macht i dus telkens 1 bit hoger
  //  1,2,4,8,16,32,64 etc.. bit 18 is 262144

}

  
CAN.sendMsgBuf(0x70,0, 4, msg);  //geen idee of dit mag... een long in één keer verzenden als 4 bytes...

.... 

Maargoed dat wordt wel lastiger om uit te werken als je dat wil coderen in 3 of 4 bytes.

dag k7jz,ik heb het gedaan zoals in het voorbeeld van gisteren en het werkt.Super bedankt voor de tijd,de uitleg en het werk!!

Top! Dankje voor de terugkoppeling.

Let op dat als je in een drukke canbus met andere apparaten gaat werken je de boel niet verstopt met overdadig veel berichten.

Je zou kunnen kijken of er wel een verandering is geweest bij de schakelaars met een extra bericht elke 5 seconden.