UP/DOWN counter met Aduino Uno

Bapaktus

Special Member

Voor een project wil ik een up/down counter maken.
Kan natuurlijk met TTL IC's.
Maar wilde met dit project het Arduino pad opgaan.
Ik kwam een voorbeeld sketch tegen van uit Indonesië .
Vertalen is geen probleem.
Sketch geladen en display op een prikbordje gezet. Verbinding gemaakt met Velleman Arduino Uno bordje.
Ik gebruik echter niet het toegepaste EDI display maar de 5461BS-1.
Common Anode uitvoering.
De schakeling op een broodplankje gemonteerd en het script opgeladen.
Liep eerst nog tegen een CH340 driver probleem op maar inmiddels compileren en uploaden geen probleem.
Alle vier de LED-segmenten "geven licht".
Maar het op en aftellen lukt niet. Wel het resetten naar 0.
Uitlezing verandert van 0000 naar 8888 en vervolgens bij de volgende puls naar 8088.
Ik ken de EDI display niet maar heb de aansluitingen van de 5461 volgens de EDI tekening aangesloten. En serie weerstanden voor de segment stroom begrenzing gemonteerd.
Zelf gemaakte eenvoudige scripts zoals timers etc werken wel.
Wat doe ik fout? Script fout of verkeerde display?
ruud

OM op afstand te weten wat er mis is... m'n glazen bol is weer eens van slag.

Maak een foto van je opstelling. Teken het schema of voeg het bij.

En /ik/ ga geen microsoft document lopen openen om een programma te bekijken. Post dat gewoon tussen code tags.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Arco

Special Member

Datasheet van de twee displays vergelijken. Dat de aansluitingen van 2 willekeurige displays hetzelfde zijn is vrij klein...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
buckfast_beekeeper

Golden Member

Schema en datasheet van het display zijn wel heel essentieel.

Code mooi ordenen met automatische opmaak (CTRL+T). Kopiëren voor het forum gebruiken (menu bewerken) en dan hier plakken tussen code tags.

Van Lambiek wordt goede geuze gemaakt.

Het aansturen van de digits gaat fout.
Voor een CA display moet je de geselecteerde digit hoog maken.

( Behalve als je een inverter in de hardware hebt toegevoegd zoals een extra transistor).

Probeer zo maar eens:

code:


void disp7seg()
{  digitalWrite(10,HIGH);
   digitalWrite(11,LOW);
   digitalWrite(12,LOW);
   digitalWrite(13,LOW);
   sevenSegWrite(cnt/1000);
   delay(5);

   digitalWrite(10,LOW);
   digitalWrite(11,HIGH);
   digitalWrite(12,LOW);
   digitalWrite(13,LOW);
   sevenSegWrite(cnt%1000/100);
   delay(5);

   digitalWrite(10,LOW);
   digitalWrite(11,LOW);
   digitalWrite(12,HIGH);
   digitalWrite(13,LOW);
   sevenSegWrite(cnt%1000%100/10);
   delay(5);

   digitalWrite(10,LOW);
   digitalWrite(11,LOW);
   digitalWrite(12,LOW);
   digitalWrite(13,HIGH);
   sevenSegWrite(cnt%1000%100%10);
   delay(5);  
}

Maar het blijft een slecht voorbeeld. Kost erg veel ram geheugen op deze manier.

En /ik/ ga geen microsoft document lopen openen om een programma te bekijken. Post dat gewoon tussen code tags.

Getweedst.

c code:


/**************************************
 * Counter Up Down Arduino UNO
 * Input : SW UP- A0
 *         SW DOWN-A1
 *         SW RESET-A2
 * Output : 7 Segment Display 4 digit CA
 * www.ardutech.com
 ***************************************/
#define up A0
#define down A1
#define rst A2
int i,j,cnt;
byte seven_seg_digits[10][7] = { 
  { 0,0,0,0,0,0,1 },  // = 0
  { 1,0,0,1,1,1,1 },  // = 1
  { 0,0,1,0,0,1,0 },  // = 2
  { 0,0,0,0,1,1,0 },  // = 3
  { 1,0,0,1,1,0,0 },  // = 4
  { 0,1,0,0,1,0,0 },  // = 5
  { 0,1,0,0,0,0,0 },  // = 6
  { 0,0,0,1,1,1,1 },  // = 7
  { 0,0,0,0,0,0,0 },  // = 8
  { 0,0,0,0,1,0,0 }   // = 9
  };
//===============================
void scan_tombol(){
  if(digitalRead(up)==LOW){
    cnt++;
    for(j=0;j<15;j++) disp7seg();   
  }  
  else if((digitalRead(down)==LOW)&&(cnt>0)){
    cnt--;
    for(j=0;j<15;j++) disp7seg();
  }  
  else if(digitalRead(rst)==LOW){
    cnt=0;
    for(j=0;j<15;j++) disp7seg();
  }
}
//===============================
void sevenSegWrite(byte segment) {
  byte pin = 2;
  for (byte segCount = 0; segCount < 7; ++segCount) {
    digitalWrite(pin, seven_seg_digits[segment][segCount]);
    ++pin;
  }
}
//=================
void disp7seg(){  
      digitalWrite(10,LOW);
      digitalWrite(11,HIGH);
      digitalWrite(12,HIGH);
      digitalWrite(13,HIGH);
      sevenSegWrite(cnt/1000);
      delay(5);
      digitalWrite(10,HIGH);
      digitalWrite(11,LOW);
       digitalWrite(12,HIGH);
      digitalWrite(13,HIGH);
      sevenSegWrite(cnt%1000/100);
      delay(5);
      digitalWrite(10,HIGH);
      digitalWrite(11,HIGH);
      digitalWrite(12,LOW);
      digitalWrite(13,HIGH);
      sevenSegWrite(cnt%1000%100/10);
      delay(5);
      digitalWrite(10,HIGH);
      digitalWrite(11,HIGH);
      digitalWrite(12,HIGH);
      digitalWrite(13,LOW);
      sevenSegWrite(cnt%1000%100%10);
      delay(5);  
}
//===============
void setup() {               
  pinMode(2, OUTPUT);  
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);  
  pinMode(10, OUTPUT); 
  pinMode(11, OUTPUT); 
  pinMode(12, OUTPUT); 
  pinMode(13, OUTPUT); 
  digitalWrite(9,HIGH);
  pinMode(A0,INPUT_PULLUP);
  pinMode(A1,INPUT_PULLUP);
  pinMode(A2,INPUT_PULLUP);  
}
//=============================   
void loop() {  
  scan_tombol();
  disp7seg();  
}

Bapaktus

Special Member

Tja, sorry heren!
Ik wilde nog foto's maken en even kijken of ik het script gewoon in mijn tweede bericht kon plaatsen. Maar tijdens het versturen van mijn bericht kwam er visite binnen, dus alles uit mijn handen laten vallen en nu pas weer achter de toetsen.
Dus de (terechte) reacties geaccepteerd.
Oók ik heb geen glazen bol, vandaar mijn vraag op dit Forum.

De laatste regel in mijn bericht noemde ik ook een mogelijke display oorzaak.
Ik weet ook niet of dat EDI display hier in Nederland bekend/leverbaar is.
Ik kon een half jaar geleden hierover niets vinden, geen intern schema of zo.
Ik ga straks de aanbevelingen c.q. opmerkingen eens goed lezen en het verbeterde script downloaden en lezen.
Iedereen bedankt
Wordt vervolgd. ruud

Bij debugging kan ook serialprint (of serialprintln) goede diensten bewijzen: bv. bij iedere wijziging van de teller doe je een serialprintln met de nieuwe tellerwaarde.
Dat zou moeten duidelijk maken of het probleem in de weergave zit dan wel in de tellogica.

benleentje

Golden Member

Zelf gemaakte eenvoudige scripts zoals timers etc werken wel.

Als je daarmee dan ook bedoelt dat het display de getallen correct weergeeft dan ligt het niet aan het display.

En dat is ook de juiste manier van debuggen onderdeel voor onderdeel is uittesten om een fout te kunnen vinden of om juist dingen uit te sluiten.

Dus nu werkt het geheel als bedoelt niet en ga dan eerst alle onderdelen apart testen.
Om te kijken of de up of dons signalen goed doorkomen kan je even tijdelijk een of meerdere leds in je programma aansturen om te kijken of die wel binnenkomen maar ook of die goed verwerkt worden.

Zo kan je ook uitvinden op een subroutine blijft hangen of een andere uitkomst geeft dan je verwacht had.

IK gebruik het liefst de seriele monitor in de Arduino IDE om te debuggenen schrijf dan op plaatsen waar ik denk dat het niet werk een regel als

c code:


void scan_tombol(){
  if(digitalRead(up)==LOW){
    cnt++;
    Serial.print("counter waarde = ");
    Serial.println(cnt);
  }


//In je setup moet dan enkel toegevoegd worden 
 Serial.begin(9600);

Zo kan je overal heel snel ziet wat wel en niet werkt. Als cnt nu op 0 blijft staan weet je dat je ingang niet goed uitgelezen word.

IK ziet wel dingen in het programma wat ik niet begrijp

c code:

for(j=0;j<15;j++) disp7seg();   

JE schrijft nu 15 keer naar het display en eigenlijk gewoon 15x dezelfde waarde want cnt is ondertussen niet verandert waar is dat voor, wat mis ik?

c code:

void loop() {  
  scan_tombol();
  disp7seg();  
}

In je scan_tombol doe je al 15x naar het display schrijven en hier nog een keer. Voor zover ik kan zien is het niet nodig om in je scan_tombol naar het display te schrijven en hoeft dat enkel in de loop() te gebeuren.

[Bericht gewijzigd door benleentje op vrijdag 3 maart 2023 18:52:19 (18%)

Mensen zijn soms net als een gelijkrichter, ze willen graag hun gelijk hebben.
buckfast_beekeeper

Golden Member

c code:

void disp7seg(){  
      digitalWrite(10,LOW);// !!!! uitgang 10 en 13 zijn nu gelijk laag. 
      digitalWrite(11,HIGH);
      digitalWrite(12,HIGH);
      digitalWrite(13,HIGH);
      sevenSegWrite(cnt/1000);
      delay(5);
      digitalWrite(10,HIGH);
      digitalWrite(11,LOW);
       digitalWrite(12,HIGH);
      digitalWrite(13,HIGH);
      sevenSegWrite(cnt%1000/100);
      delay(5);
      digitalWrite(10,HIGH);
      digitalWrite(11,HIGH);
      digitalWrite(12,LOW);
      digitalWrite(13,HIGH);
      sevenSegWrite(cnt%1000%100/10);
      delay(5);
      digitalWrite(10,HIGH);
      digitalWrite(11,HIGH);
      digitalWrite(12,HIGH);
      digitalWrite(13,LOW);
      sevenSegWrite(cnt%1000%100%10);
      delay(5);  
}

Kan sowieso een stuk korter. Waarom een uitgang hoog maken die al hoog is uit de vorige actie?

c code:

void disp7seg(){        
      digitalWrite(11,HIGH);// uit voorzorg alle niet te gebruiken uitgangen hoog maken
      digitalWrite(12,HIGH);
      digitalWrite(13,HIGH);
      sevenSegWrite(cnt/1000);// eerst nieuwe waarde klaar zetten dan pas display aan zetten. 
      digitalWrite(10,LOW);// als laatste te gebruiken uitgang laag maken      
      delay(5);
      digitalWrite(10,HIGH);
      sevenSegWrite(cnt%1000/100);
      digitalWrite(11,LOW);
      delay(5);
      digitalWrite(11,HIGH);     
      sevenSegWrite(cnt%1000%100/10);
      digitalWrite(12,LOW); 
      delay(5);
      digitalWrite(12,HIGH);
      sevenSegWrite(cnt%1000%100%10);
      digitalWrite(13,LOW);
      delay(5);  
}

Nadeel van deze werkwijze is dat het laatste digit altijd feller zal weergegeven worden wegens langer aangestuurd als de anderen. Normaal probeer je dit op te lossen met een solid state machine en niet met delay.

Van Lambiek wordt goede geuze gemaakt.
Bapaktus

Special Member

@buckfast_beekeeper

Ik heb de code aangepast.
LOW naar HIGH en High naar LOW
Het werkt _/-\o_
Ik was er vanuit gegaan dat ik, wanneer ik precies de verbindingen zou maken zoals aangegeven (en wel drie keer had gecontroleerd) de Display's correct zouden worden aangestuurd.
Bij het zojuist opnieuw zoeken naar de gegevens van dat andere display las ik ook de tekst dat in die display weerstanden en transistors zitten.
Had mij aan het denken moeten zetten. :(
De aanwijzing wordt verhoogt of verlaagt bij het indrukken van 1 van de knoppen.
En ook het resetten naar 0 werkt.

@benleentje
Als je daarmee dan ook bedoelt dat het display de getallen correct weergeeft dan ligt het niet aan het display.
Dat waren sketch's die geschreven waren voor het door mij gebruikte display.
En dat werkte wel.

Maar goed , ik ben , dank zij jullie, weer een stukje wijzer geworden, ik zal nog vele valkuilen tegen komen.
Iedereen bedankt, ruud

Arco

Special Member

Voor displayselectie gebruik je eigenlijk altijd een transistor ertussen.
Anders moet de i/o pin veel te veel stroom gaan leveren (20+ mA)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bapaktus

Special Member

@Arco

Voor displayselectie gebruik je eigenlijk altijd een transistor ertussen.
Anders moet de i/o pin veel te veel stroom gaan leveren (20+ mA)

In de spec's van de Velleman UNO staat dat de I/O pin 40 mA mag/kan leveren.
Met een 1kOhm weerstand per segment gebruik ik maximaal (gemeten zonder multiplexen) voor 7 segmenten 21 mA.
En omdat per display gemultiplexed wordt zal dit ook wel schelen in de stroom (warmte ontwikkeling) per display.
Maar het toepassen van 4 transistors voor de display selectie is natuurlijk ook mogelijk.
Ga ik over nadenken.
Het zijn kleine stapjes in mijn kennis toename. Heel wat anders dan UHF-SHF schakelingen-antennes.
Maar bedankt voor het meedenken, ruud

benleentje

Golden Member

Dat waren sketch's die geschreven waren voor het door mij gebruikte display.
En dat werkte wel.

Dan weet je dus dat je display goed is en je arduino die goed kan aansturen als het dan in een andere sketch niet werkt dan weet je dus dat de sketch verkeerd is voor je display en dat he dus niet aan je display zelf ligt. Dat is ook een onderdeel van debugen of anders gezegd fouten in je soft en hardware opsporen. Uitzoeken wat wel en niet werk totdat het geheel werkt zoals je het wilt.

[Bericht gewijzigd door benleentje op vrijdag 3 maart 2023 23:06:37 (41%)

Mensen zijn soms net als een gelijkrichter, ze willen graag hun gelijk hebben.
Arco

Special Member

Op 3 maart 2023 22:51:13 schreef Bapaktus:
@Arco
[...]

In de spec's van de Velleman UNO staat dat de I/O pin 40 mA mag/kan leveren.

Weer eens iemand die de Absolute Maximum Ratings met de specs verwart...
De 'Absolute Maximum Ratings zijn geen specs, maar de uiterste waarde waarboven de boel wordt opgeblazen, die ratings nooit gebruiken!

De werkelijk te leveren stroom is veel lager.
(stroom wordt meestal gespecificeerd op de waarde waarop de output de gevraagde logische TTL nivo's nog net kan leveren. Geloof me, da's veel minder als 40mA)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Naast de discussie over de max stroom van een pin...

Mijn voorstel is dat je niet iemand hier je programma laat corrigeren naar iets wat geschikt is voor jou display, maar dat je probeert het zelf te doen. Daar leer je veel meer van.

Probeer eerst 1 segmentje aan te krijgen. (common) anode hoog, segment lijn van het segmentje laag.

Probeer nu te verzinnen hoe je het kan veranderen om een ander segment aan te krijgen.

Daarna kan je proberen twee segmenten tegelijk te doen.

Vervolgens: "laat 1 cijfer zien".

en als dat lukt: laat vier cijfers zien!

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Inderdaad. Probleem: "het werkt niet (zoals bedoeld)".
Oplossing: probleem opdelen in deelproblemen. Werkt teller? Werkt displayhardware? Werkt displaysoftware?
Deelprobleem waar het op aankomt verder opsplitsen.

Nu, toegegeven, commentaar achteraf is gemakkelijk...
Het werkt nu, en daar komt het maar op aan. Proficiat!

buckfast_beekeeper

Golden Member

Op 4 maart 2023 10:25:18 schreef rew:
[...]
Mijn voorstel is dat je niet iemand hier je programma laat corrigeren naar iets wat geschikt is voor jou display, maar dat je probeert het zelf te doen. Daar leer je veel meer van.
[...]

Niet 100% mee akkoord. Een goed voorbeeld krijgen en doorgronden waarom het wel werkt en het uwe niet werkte is minstens even leerzaam. Als je dan een bepaalde zaak niet begrijpt, gericht een vraag stellen is beter als aanmodderen en niet weten wat je deed. Het werkt maar ik weet niet hoe het komt, wat heb je dan geleerd?

Op 3 maart 2023 23:18:12 schreef Arco:
[...]
Weer eens iemand die de Absolute Maximum Ratings met de specs verwart...
De 'Absolute Maximum Ratings zijn geen specs, maar de uiterste waarde waarboven de boel wordt opgeblazen, die ratings nooit gebruiken!

De werkelijk te leveren stroom is veel lager.
(stroom wordt meestal gespecificeerd op de waarde waarop de output de gevraagde logische TTL nivo's nog net kan leveren. Geloof me, da's veel minder als 40mA)

100% akkoord. Zelfs 20mA per uitgang kan al teveel zijn. Er is ook een maximum voor een groep uitgangen. Uit de datasheet

Zie vooral nota 3 en 4.

Buiten een ledje van 2mA of een enkele led van 20mA is het geen goed idee iets uit de µC te voeden. Een ULN2003/ULN2803 (sinken), MIC2981 (source), transistor of logic level mosfet is meer dan aangeraden.

Van Lambiek wordt goede geuze gemaakt.
Bapaktus

Special Member

@BFBK
Buiten een ledje van 2mA of een enkele led van 20mA is het geen goed idee iets uit de µC te voeden. Een ULN2003/ULN2803 (sinken), MIC2981 (source), transistor of logic level mosfet is meer dan aangeraden.

Vraag 1: wanneer ik een CA buffer gebruik (MIC2981) voor de 4 Digit selectie aansturing (voeden van af de UNO 5 Volt power-pin) én in de segment aansturing 1 kOhm weerstanden gebruik, moet dit toch voldoende zijn?

Vraag 2: (Ik heb gezocht naar een antwoord maar (nog) niet kunnen vinden.)
Waarom wordt er tussen de Digit selectie een delay van "(5)" gebruikt? De belasting is toch Ohms? Of gaat de bedradings capaciteit/inductie een rol spelen?

void disp7seg(){
digitalWrite(10,LOW);// !!!! uitgang 10 en 13 zijn nu gelijk laag.
digitalWrite(11,HIGH);
digitalWrite(12,HIGH);
digitalWrite(13,HIGH);
sevenSegWrite(cnt/1000);
delay(5);
digitalWrite(10,HIGH);
digitalWrite(11,LOW);
digitalWrite(12,HIGH);
digitalWrite(13,HIGH);

buckfast_beekeeper

Golden Member

Antwoord 1:Met buffers/drivers er tussen is er eigenlijk niet echt een limiet. Ga je vanaf de UNO voeden, dan is de stroom die het printje kan leveren de limiet. Ga je voeden met een externe 5V dan wordt de voeding de limiet.

Antwoord 2: delay(5) zorgt er voor dat de uitvoering van het programma 5ms wordt stopgezet. In dit geval is dat de tijd dat er wordt gewacht voor het volgende digit wordt getoond.

In de praktijk moet je met delay heel voorzichtig omspringen. Vraag telkens af of het verantwoord is dat je programma volledig stopt. In setup gebruik ik het wel als bepaalde opstartteksten op een scherm worden getoond of na het opstarten van WiFi. In loop is het beter 'blink without delay' te gebruiken.

Van Lambiek wordt goede geuze gemaakt.
Arco

Special Member

Zonder delay zouden de displays als een dolle ververst blijven worden:
Zonde van de gebruikte tijd (hoewel in een delay de processor natuurlijk ook niks zinnigs doet...) en het display wordt minder duidelijk.
Bij multiplexen moet je nu eenmaal geduld hebben... :)

[Bericht gewijzigd door Arco op maandag 6 maart 2023 14:59:41 (17%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
buckfast_beekeeper

Golden Member

Dat verversen kan je ook op een andere manier regelen. Bijvoorbeeld een timer interrupt kan al een oplossing zijn.

Met bovenstaande code heb je het probleem dat het laatst getoonde digit feller zal zijn als de andere. Je hebt niet alleen de delay van 5ms maar ook de tijd van de loop tot de procedure terug wordt aangeroepen. Steek ook daar nog een paar delay in en het verschil wordt heel duidelijk.

edit: @MGP: Ook het programmeren zorgt daarvoor. In de gegeven code van het starttopic wordt CA aangestuurd VOOR de waarde wordt gewijzigd. Uiteraard staat dan de waarde van het vorige digit op het nieuwe digit.

Eerst vorige digit uit zetten. Nieuwe waarde op de uitgangen zetten en dan het nieuwe digit aan.

[Bericht gewijzigd door buckfast_beekeeper op maandag 6 maart 2023 16:27:25 (28%)

Van Lambiek wordt goede geuze gemaakt.

Zonder delays krijg je schaduwbeelden, dwz dat je heel zwak het vorige cijfer nog kunt zien op het nieuwe cijfer, vooral in het donker valt dat goed op.
Het houdt verband met de schakelsnelheid van de ULNxxxx's of transistoren.

LDmicro user.
benleentje

Golden Member

Waarom wordt er tussen de Digit selectie een delay van "(5)"

Een led (display ) is heel erg snel. Elke digit word maar heel even kort aangestuurd en dan snel naar het volgende. Gelukkig is ons menselijk oog + hersenen weer traag en ook als de digit al is gedoofd denken onze hersenen nog dat het er staat. Maar om dat voor elkaar te krijgen moet het digit wel even genoeg licht hebben gegeven. Dat kan met bv een grote stroom als normaal en of een wat langere oplichttijd. Een display wat bv maar 20mA per led mag hebben mag als die gemultiplexed word bv 100mA of meer hebben.

Er is dus een zekere tijd nodig om het segment lang genoeg aan te sturen om het brein het idee te geven dat het continu aan is. Dt oplossen met een delay is de meeste eenvoudige manier maar zeker niet de beste. Maar soms is eenvoudig ook goed genoeg en kan je wel moeilijk gaan doen maar als dat verder niets oplevert kan je het net zo goed zo laten. Maar de sport om het wel zonder delay te doen levert dan ook ook weer wat op.
Een delay is blokkerende code voor de microcontroller het kan dan niets anders doen en ook ook niet bv een schakelaar uitlezen omdat jij een knop indrukt. Voor 7 segmenten is dat 7x 5mS = 35mS. Dat is voor een knop in te drukken nog net te doen. Maar het voelt voor de gebruiker toch als het reageert niet direct.

Een cpu die op 20Mhz werkt = 20.000 instructies per mS >> 100.000 instructie wachten en niets doen. Dus eigenlijk veel weggegooide tijd.

Mensen zijn soms net als een gelijkrichter, ze willen graag hun gelijk hebben.