RS485 naar TTL-RS232 module

Op de RS485 module staat aan de ene kant DI De RE RO en aan de andere kant Vcc B A Gnd. De verbinding met de Arduino is:

DI -> TX
DE -> pin 3
RE -> pin 4
RO -> RX

oplossing looplicht met twee schuifregisters (16 bit)

 

const int patroon[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
const int ds = 2;
const int stclk = 3;
const int shclk = 4;

void setup()
{
  for(int i=2; i<=4;i++) {
      pinMode(i, OUTPUT);
  }
}

void loop()
{
  int aantal=sizeof(patroon)/sizeof(patroon[0]);
  for(int i=0; i<aantal;i++) {
    for(int bit=0;bit<16;bit++) {
      if(bitRead(patroon[i],bit)==1) {
        digitalWrite(ds,1);}
      else {
        digitalWrite(ds,0);}
      // puls op shiftklok
      digitalWrite(shclk,HIGH);
      digitalWrite(shclk,LOW);
    }
    // puls op storage klok
    digitalWrite(stclk,HIGH);
    digitalWrite(stclk,LOW);
    delay(500);
  }
}

Oplossing looplicht met schuifregister.

In onderstaande code maken we een algemene oplossing die niet alleen voor een looplicht kan dienen, maar voor gelijk welke combinatie van patronen, zolang het maar beperkt blijft tot 8 leds.

Deze oplossing is een combinatie van een datastructuur (een array) en een programmastructuur die met deze datastructuur aan de slag gaat. Helemaal onderaan vind je het totaalprogramma, maar we bekijken eerst stuk per stuk de code.

definitie van de constanten

const int patroon[]={1,2,4,8,16,32,64,128};
const int ds = 2; 
const int stclk = 3; 
const int shclk = 4;

de array

Zoals eerder gezegd maken we gebruik van een array om de te tonen patronen op te slaan. Bij een array definiëren we een variabele of constante die uit een reeks van waarden bestaat. Elk element wordt aangegeven met een indexnummer.

In ons programma maken we op de eerste lijn een array aan. De variabele heet patroon en het type van de variabele is integer. Door de vierkante haakjes na de naam geven we aan dat het om een reeks van integer waarden gaat. Aan deze reeks wordt een verzameling van waarden toegekend. Deze worden opgesomd tussen accolades.

Er staan 8 waarden opgesomd tussen de accolades, dus wordt in het geheugen plaats gereserveerd voor 8 integers. Aangezien een integer twee geheugenplaatsen inneemt, zal in het geheugen 16 byte gereserveerd worden voor deze array.

Eenmaal deze definitie gebeurd is, beschikken we over 8 constante waarden, aangegeven als patroon[0], patroon[1],... patroon[7], waarbij patroon[0]=1, patroon[1]=2, patroon[3]=4,... en patroon[7]=128.

Wanneer we een array van variabelen (dus geen constanten) definiëren, weten we soms op  voorhand niet welke waarden in elke variabele zullen terechtkomen. Dan is het mogelijk om een definitie te maken op volgende manier:

int resultaat[8];

Hierbij worden ook 8 waarden gedefinieerd. Merk op dat het aantal elementen hier tussen de vierkante haakjes staat, terwijl er bij een opsomming niets tussen de vierkante haakjes staat.

Zo zal een definitie zoals

int waarde[3]={1,2,3};

een foutmelding geven bij het compileren, omdat de waarde tussen de vierkante haken mogelijks niet kan overeenkomen met het aantal elementen in de opsomming. We moeten dus altijd de ene of de andere manier gebruiken, maar geen combinatie.

de pinnummers

In lijnen 2 tot 4 van de definitie geven we betekenisvolle namen aan de gebruikte pinnen die de verbinding met het schuifregister maken. Zo wordt pin 2 vanaf nu aangeduid met ds, pin 3 met stclk en pin 4 met shclk. Deze namen zijn respectievelijk data-serial, storage clock en shift clock.

de setup() functie

Tijdens de setup worden pinnen 2 tot en met 4 als output ingesteld. We doen dit met behulp van een lus.

void setup() { 
for(int i=2; i<=4;i++) {
 pinMode(i, OUTPUT);
 }
}

de loop() functie

In de loop() functie beginnen we met het bepalen van het aantal elementen in de array. Op die manier kunnen we achteraf patronen aan de array toevoegen zonder dat we elke keer in het programma het aantal elementen moeten aanpassen. We maken daarvoor gebruik van de functie sizeof(). Deze functie geeft aan hoeveel bytes de aangegeven variabele inneemt in het geheugen. Het resultaat van sizeof(patroon) zal 16 zijn, zoals we eerder reeds hebben uitgelegd. Als we dit resultaat delen door de grootte van 1 element bekomen we het aantal elementen in de array. Een integer is 2 bytes groot, dus delen we het resultaat van de sizeof() functie door 2.

Opmerkingen

Wanneer we de array aanvullen met extra waarden, zal deze berekening automatisch het aantal elementen weergeven. Als we echter het type van de patroon variabele veranderen zal deze uitdrukking een fout resultaat geven. Een truc om dit te vermijden is om gebruik te maken van volgende uitdrukking:

int aantal = sizeof(patroon)/sizeof(patroon[0]);

Door de grootte van de array te delen door de grootte van het eerste element krijgen we een resultaat, onafhankelijk van het type van de elementen van de array. Het enige type waarbij dit niet werkt is uiteraard de string, aangezien deze zelf een variabele lengte heeft.

Vervolgens maken we een lus met een teller i die de elementen van de array doorloopt. In deze lus maken we een tweede (geneste) lus, die voor elk van de elementen van de array de 8 bits doorloopt. Hier gebruiken we als teller de variabele bit.
We gaan in deze lus de waarde van de opeenvolgende bits op de seriële ingang van het schuifregister (=ds) plaatsen en na elke bit een klokpuls op de shiftclock (=shclk) geven om de bit in het schuifregister te schuiven. Aangezien deze lus 8 keer doorlopen wordt zullen de 8 bits van de waarde na het doorlopen van de lus in het schuifregister staan. Daarna wordt een puls op de storage clock (=stclk) gegeven, waardoor de inhoud van het schuifregister in het storage register gekopieerd wordt, en tegelijkertijd ook op de uitgangen van het schuifregister zichtbaar wordt.
Daarna wordt 500 ms gewacht waarna het volgende element uit de array dezelfde behandeling krijgt.
Wanneer de volledige array werd doorlopen begint alles opnieuw van voor af aan.
Om de juiste bit van het juiste patroon op de ingang van het schuifregister te plaatsen maken we gebruik van een bit-functie bitRead(). Deze functie heeft twee parameters nodig: de waarde waaruit de bit moet worden gelezen, en de bitpositie die moet worden gelezen. Resultaat van deze functie is 0 of 1, afhankelijk van de waarde op de gevraagde bitpositie.
Bij de eerste doorloop van de lussen is teller i gelijk aan 0, en is teller bit ook gelijk aan 0. De uitdrukking patroon[0] is in dit geval gelijk aan 1 (eerste element uit de array). Binair uitgeschreven is dit 00000001.
bitRead(patroon[0],0) geeft dus de waarde van de meest rechtse bit in 00000001 en is dus 1.
De if-functie zorgt er dan voor dat op de ds-ingang een 1 geplaatst wordt.
void loop() {
 int aantal=sizeof(patroon)/2;
 for(int i=0; i<aantal;i++) {
   for(int bit=0;bit<8;bit++) {
     if(bitRead(patroon[i],bit)==1) {
       digitalWrite(ds,1);
       } else {
       digitalWrite(ds,0);
       }
     // puls op shiftklok
     digitalWrite(shclk,HIGH);
     digitalWrite(shclk,LOW);
     } 
    // puls op storage klok
   digitalWrite(stclk,HIGH);
   digitalWrite(stclk,LOW);
   delay(500);
  }
}

de totale oplossing

const int patroon[]={1,2,4,8,16,32,64,128};
const int ds = 2;
const int stclk = 3;
const int shclk = 4;

void setup()
{
  for(int i=2; i<=4;i++) {
      pinMode(i, OUTPUT);
  }
}

void loop()
{
  int aantal=sizeof(patroon)/2;
  for(int i=0; i<aantal;i++) {
    for(int bit=0;bit<8;bit++) {
      if(bitRead(patroon[i],bit)==1) {
        digitalWrite(ds,1);}
      else {
        digitalWrite(ds,0);}
      // puls op shiftklok
      digitalWrite(shclk,HIGH);
      digitalWrite(shclk,LOW);
    }
    // puls op storage klok
    digitalWrite(stclk,HIGH);
    digitalWrite(stclk,LOW);
    delay(500);
  }
}