beste mensen,
voor een project van school moeten we een muntenteller maken. Die zal gestuurd worden door een µC, nl de PIC16F876A.
Ik heb mezelf de afgelopen tijd wat zitten verdiepen in de wereld van de microcontrollers en ben bij mikroBasic uitgekomen als compiler omdat de gratis versie toch nog 2k aan code kan genereren en omdat basic me de gemakkelijkste taal lijkt om snel een behoorlijk resultaat te bekomen. Nu heb ik problemen met mijn programmer (K8048 van velleman) en heb ik dus niets om mijn code te kunnen testen (op school kan het wel maar dat duurt iets te lang).
Hetgeen ik nu al geschreven heb kan (hoop ik) munten tellen en dat weergeven op een LCD-tje. Wat denken jullie ervan? Zal het werken?
program muntenteller
'gemaakt voor de PIC16F876A
'DOEL: programma voor een muntenteller
'FUNCTIES: 8 sensoren die munten tellen, 3 knoppen, LCD scherm voor de output
'LCD scherm: 9 boodschappen, te secteren met 2 knoppen
'PORTA bevat de knoppen, PORTB bevat de sensoren en PORTC
'zorgt voor het LCD scherm
'*******************************************************************************
' ***ALGEMEEN***
'*******************************************************************************
symbol volgend_scherm = PORTA.1 'de eerste knop wordt gedefinieerd
symbol vorig_scherm = PORTA.0 'de tweede knop wordt gedefinieerd
symbol reset_knop = PORTA.2 'de derde knop wordt gedefinieerd
symbol telsensor1 = PORTB.0 'de eerste telsensor wordt gedefinieerd
symbol telsensor2 = PORTB.1 'de tweede telsensor wordt gedefinieerd
symbol telsensor3 = PORTB.2 'de derde telsensor wordt gedefinieerd
symbol telsensor4 = PORTB.3 'de vierde telsensor wordt gedefinieerd
symbol telsensor5 = PORTB.4 'de vijfde telsensor wordt gedefinieerd
symbol telsensor6 = PORTB.5 'de zesde telsensor wordt gedefinieerd
symbol telsensor7 = PORTB.6 'de zevende telsensor wordt gedefinieerd
symbol telsensor8 = PORTB.7 'de achtste telsensor wordt gedefinieerd
dim een_cent as byte 'iedere muntsoort krijgt zijn
dim twee_cent as byte 'eigen variabele
dim vijf_cent as byte
dim tien_cent as byte
dim twintig_cent as byte
dim vijftig_cent as byte
dim een_euro as byte
dim twee_euro as byte
dim schermteller as byte 'deze variable houdt de 9 verschillende
'schermen in
'*******************************************************************************
' ***BODY***
'*******************************************************************************
main: 'label om het begin aan te duiden
'hier begint het tel gedeelte
TRISA = 1 'poorten A,B en C worden geconfigureerd
TRISB = 1 ' 1 = ingang, 0 = uitgang
TRISC = 0
Lcd_Init(PORTC) 'het scherm wordt ge-initialiseerd
schermteller = 0 'var schermteller wordt op nul gezet
een_cent = 0 'var van de munten worden op nul gezet
twee_cent = 0 ' om te beginnen vanaf nul
vijf_cent = 0
tien_cent = 0
twintig_cent = 0
vijftig_cent = 0
een_euro = 0
twee_euro = 0
Teller: 'label voor de loop
if telsensor1 = high then 'indien de sensor een munt waarneemt...
INC een_cent 'telt hij er eentje bij de variabele
end if '...anders niet
if telsensor2 = high then
INC twee_cent
end if
if telsensor3 = high then
INC vijf_cent
end if
if telsensor4 = high then
INC tien_cent
end if
if telsensor5 = high then
INC twintig_cent
end if
if telsensor6 = high then
INC vijftig_cent
end if
if telsensor7 = high then
INC een_euro
end if
if telsensor8 = high then
INC twee_euro
end if
'hier begint het scherm gedeelte
if volgend_scherm = high then 'indien de knop ingedrukt word...
INC schermteller 'dan wordt de var schermteller één hoger
end if '...anders niet
if vorig_scherm = high then 'indien de knop ingedrukt word...
DEC schermteller 'dan wordt de var schermteller één lager
end if '...anders niet
if schermteller = 9 then '9 schermteksten, 8 status en 1 totaal (0-8)
schermteller = 0 'wanneer de var 9 wordt, wordt hij opnieuw
end if 'bij het begin gezet
if schermteller = 0 then 'afhankelijk van de var schermteller wordt
Lcd_Out(1, 1, Aantal munten= een_cent) 'een tekst op het scherm gezet
else ' gepaste variabele incluis
if schermteller = 1 then
Lcd_Out(1, 1, Aantal munten= twee_cent)
else
if schermteller = 2 then
Lcd_Out(1, 1, Aantal munten= vijf_cent)
else
if schermteller = 3 then
Lcd_Out(1, 1, Aantal munten= tien_cent)
else
if schermteller = 4 then
Lcd_Out(1, 1, Aantal munten= twintig_cent)
else
if schermteller = 5 then
Lcd_Out(1, 1, Aantal munten= vijftig_cent)
else
if schermteller = 6 then
Lcd_Out(1, 1, Aantal munten= een_euro)
else
if schermteller = 7 then
Lcd_Out(1, 1, Aantal munten= twee_euro)
end if
end if
end if
end if
end if
end if
end if
end if
if reset_knop = high then 'de reset wordt ingedrukt en dan
goto main 'gaat het programma terug naar main
else 'anders
goto Teller 'gaat het programma terug naar Teller
end if
End. 'einde
Sorry voor die lange post, ik hoop dat jullie me kunnen helpen en dat alles duidelijk is
Groeten, wartos
Erik
In order to succeed you must fail, so that you know what not to do the next time.
En dit gaat denk ik ook niet werken of de taalstructuur moet behoorlijk gaar zijn. die lange else if loop zou zo niet gaan werken omdat je gebruik moet maken van elseif of in sommige talen elsif.
Maar zoals shortcircuit al zegt gebruik een case achtig iets om het te verwerken.
Dank je voor het snelle commentaar, van zulke dingen leer ik nu - ik had nog nooit gehoord van een CASE structuur.
Na wat help files te doorspitten heb ik nu het volgende:
*zie FP voor het geheel*
'hier begint het scherm gedeelte
if volgend_scherm = high then 'indien de knop ingedrukt word...
INC schermteller 'dan wordt de var schermteller één hoger
end if '...anders niet
if vorig_scherm = high then 'indien de knop ingedrukt word...
DEC schermteller 'dan wordt de var schermteller één lager
end if '...anders niet
select case schermteller 'afhankelijk van de var schermteller wordt
case 0 'een tekst op het scherm gezet
Lcd_Out(1, 1, Aantal munten= een_cent)
case 1
Lcd_Out(1, 1, Aantal munten= twee_cent)
case 2
Lcd_Out(1, 1, Aantal munten= vijf_cent)
case 3
Lcd_Out(1, 1, Aantal munten= tien_cent)
case 4
Lcd_Out(1, 1, Aantal munten= twintig_cent)
case 5
Lcd_Out(1, 1, Aantal munten= vijftig_cent)
case 6
Lcd_Out(1, 1, Aantal munten= een_euro)
case 7
Lcd_Out(1, 1, Aantal munten= twee_euro)
case 8
Lcd_Out(1, 1, Aantal munten= Totaal)
case else
schermteller = 0
end select
if reset_knop = high then 'de reset wordt ingedrukt en dan
goto main 'gaat het programma terug naar main
else 'anders
goto Teller 'gaat het programma terug naar Teller
end if
End. 'einde
Nog meer hints, tips?
Wat ik me ook afvraag is het volgende: wanneer een munt voorbij de sensor valt, zal die sensor dan niet te lang een signaal geven (zodat hij er eigenlijk tien ofzo telt)?
Ik dacht dit op te lossen door enkele delays, maar ik denk dat hij dan op enkele andere plaatsen munten niet zal tellen... Suggesties?
groeten, wartos
PS: dit is mijn eerste programmeer-ervaring en voorlopig is het werkend krijgen mijn hoogste prioriteit
Erik
In order to succeed you must fail, so that you know what not to do the next time.
je zal op deze manier zeker weten een delay in moeten bouwen. Je micro is veels te snel voor een vallend muntje. Maar zet die delay bijvoorbeeld op 250ms/500ms, dan is het muntje er allang doorheen en dan heb je denk ik nog niet de kans gehad om een volgende erin te stoppen.
En dit:
if telsensor2 = high then
INC twee_cent
end if
if telsensor3 = high then
INC vijf_cent
end if
if telsensor4 = high then
INC tien_cent
end if
if telsensor5 = high then
INC twintig_cent
end if
if telsensor6 = high then
INC vijftig_cent
end if
if telsensor7 = high then
INC een_euro
end if
if telsensor8 = high then
INC twee_euro
end if
kun je oplossen door bijv te doen
if telsensor2 = high then
INC twee_cent
elseif telsensor3 = high then
INC vijf_cent
elseif.... enz
INC ...
end if
Als je klaar bent dan hoef je maar eenmalig end if te typen. Je moet even zien of mijn voorbeeld zo klopt(programmeer normaal in andere talen) maar zo te zien moet het wel goedkomen
[Bericht gewijzigd door Erik op ]
Hmm misschien maar het grote probleem is dat er zowat 8 muntjes tegelijk kunnen vallen, theoretisch dan toch (in ieder gaatje één)
in ieder geval; een goeie nacht!
wartos
positieve flankdetectie gebruiken op de sensor die de munten telt...!!!
ook op de increment / decrement van de schermteller en reset knop een positieve flank detecteren...
de µc is zodanig snel dat ie bij een hoog signaal van de inputs blijft doortellen zolang de drukknop ingedrukt is...
positieve flank detecteert enkel 1 muntje of in het geval de +- knoppen 1 waarde wijziging
je zal ook een debounce of ontdendering moeten inbouwen...
onthou 1 ding : gebruik zo weinig mogelijk delays, das schimmel op de kaas in software.
[Bericht gewijzigd door shortcircuit op ]
Roland van Leusden
It's the rule that you live by and die for It's the one thing you can't deny Even though you don't know what the price is. It is justified.
Heeft die PIC geen "on pin change" interrupt zoals de AVR ?
<Edit> Zelf maar even Google gedaan:
http://www.mikroe.com/en/books/picbook/2_07chapter.htm
[Bericht gewijzigd door Roland van Leusden op ]
ik zou in dit geval toch opteren om zelf + flanken te programmeren en een debounce functie...
die interrupts zullen theoretisch wel werken maar de sensor zal bij 1 muntje toch denderen en filtert die on change functie van pic die eruit ?
[Bericht gewijzigd door shortcircuit op ]
je kan ook je prog ferm inkorten door slechts 1 lcd_out te programmeren en gebruik te maken van een string variable om je munten te displayen ifv de schermteller,...
Dank je voor de input shortcircuit, maar je praat nu toch een beetje chinees voor mij vrees ik.
een positieve flank detecteren... euh dat doet me denken aan transistors maar ik zit wss fout, of is het softwarematig?
Dat met die string variabele zal ik eens bestuderen, straks zal ik mijn code posten als ik iets goed vind.
Ik ga nu eerst de link van roland checken...
Positieve flank detecteren is puur softwarematig
voor een avr doe ik het meestal zo...
voor - flankdetectie
bitwait portA.0,SET
bitwait portA.0,RESET
voor + flankdetectie
bitwait portA.0,RESET
bitwait portA.0,SET
algemeen (S5/S7 siemens) doe ik het zo:
U M0.0 TE BEWAKEN SIGNAAL
UN M0.2 HULPBITJE
= M0.1 ONE SHOT BITJE
U M0.0
= M0.2
met wat if thens is dat ook te gebruiken in pic of avr
het laatste heeft in deze toepassing mijn voorkeur omdat het programma niet stop en blijft scannen...
je kan ook ergens een interrupt + of - flank configureren geloof ik... maar jij hebt minstens 9 flankdetecties nodig.
er bestaat ook een algoritme om op een byte een detectie te doen maar die vind ik ff niet terug...
[Bericht gewijzigd door shortcircuit op ]
Roland van Leusden
It's the rule that you live by and die for It's the one thing you can't deny Even though you don't know what the price is. It is justified.
Op 5 maart 2007 09:51:37 schreef shortcircuit:
ik zou in dit geval toch opteren om zelf + flanken te programmeren en een debounce functie...die interrupts zullen theoretisch wel werken maar de sensor zal bij 1 muntje toch denderen en filtert die on change functie van pic die eruit ?
Volgens mij wel.
If they are defined as input, their current state is compared to the old value which was stored at the last reading from port B.
Probleem is dat de gebruikte uC maar 4 pinnen met on pin change interrupt heeft. Een i2c mcp23016 i/o extender kun je ook goed gebruiken hiervoor.
Dank je voor het meeredeneren allemaal!
1. De PIC16F876A (de 28 pins versie van de 877A) heeft volgens zijn datasheet 14 interrupts(heb er minimaal 11 nodig), maar het ziet er ingewikkeld uit. als het makkelijker kan...
2. Shortcircuit, wat bedoel je eigelijk met die string variabels?
Hier staat de info erover, maar waarom zou ik dat gebruiken? (vragend bedoeld)
3. Dat met die flanken, kan iemand meer uitleg geven?
Ik denk dat shortcircuit bedoelt dat de µC ziet dat een input hoog wordt en vervolgens er eentje bij telt wanneer diezelfde input opnieuw laag wordt, en niet vroeger. Dat zou mooi zijn, alleen, hoe moet ik dat doen in basic? Heeft iemand trefwoorden voor google, voorbeelden van code of ervaring met telprogramma's die werken met externe invloeden?
4.
Teller: 'label voor de loop
if telsensor1 = high then 'indien de sensor een munt waarneemt...
INC een_cent 'telt hij er eentje bij de variabele
else if telsensor2 = high then '...anders niet
INC twee_cent
else if telsensor3 = high then
INC vijf_cent
else if telsensor4 = high then
INC tien_cent
else if telsensor5 = high then
INC twintig_cent
else if telsensor6 = high then
INC vijftig_cent
else if telsensor7 = high then
INC een_euro
else if telsensor8 = high then
INC twee_euro
end if
dit stukje heb ik opnieuw geschreven, ik hoop dat het werkt
groeten
string variablen zijn variablen die text kunnen bevatten
je zou dan de string variable kunnen vullen met de gewenste text ifv de schermteller en dan op het einde van het programma slechts 1 lcd_out (met de string var) programmeren.
positieve flank:
een hoog signaal wordt gedecteerd terwijl het signaal vorige cycle laag was
negatieve flank:
een laag signaal wordt gedecteerd terwijl het signaal vorige cycle hoog was
hieronder pseudo code voor een positieve flank met if then's
ONE SHOT BITJE = 0
IF (TE BEWAKEN SIGNAAL) = 1 AND (HULPBITJE) = 0 THEN
ONE SHOT BITJE = 1
ENDIF
HULPBITJE = TE BEWAKEN SIGNAAL
het ONE SHOT BITJE is slechts 1 cycle hoog waarmee het mogelijk is om tiptoetsen te maken.
[Bericht gewijzigd door shortcircuit op ]
dit zou je ook eventueel kunnen gebruiken om de munten te tellen
for x = 0 to 7
if portb.x = 1 then
inc munt(x)
endif
next x
Een lichtje gaat bij me branden
voorbeeld:
symbol telsensor = PORTB.0
dim munt as byte
dim controlebit, opteller, as bit
telsensor = 0
main:
opteller = 0
if controlebit = 0 AND telsensor = 1 then
opteller = 1
end if
controlebit = telsensor
if opteller = 1 then
INC munt
end if
goto main
end.
poging tot waarheidstabel:
controlebit | telsensor || opteller | munt
| || |
0 | 0 || 0 | 0
0 | 1 || 1 | 1
1 | 0 || 0 | 0
1 | 1 || 0 | 0
opnieuw
0 | 0 || 0 | 0
0 | 1 || 1 | 2
1 | 0 || 0 | 0
1 | 1 || 0 | 0
hartelijk dank!
ik ga dit even verwerken en dan post ik de nieuwe broncode
groeten
je kan ook altijd een subroutine schrijven voor een flank detectie en dan dmv vars steeds een andere gebruiken,
tis maar een voorstel 
Nou sorry daarvoor maar de programmer werkt nu en het blijkt dat de aansturing van de knoppen niet eens werkt(het lcd trouwens ook niet) dus ik ben bezig vanalles aan het testen, spijtig genoeg schiet het niet echt op want de code schrijven is niet het enige dat moet gebeuren...
wanneer het betert zal ik zeker de code posten 
Jeroen Boere
IF you can't convince them, then confuse them!
volgens mij gaat dit niet op:
TRISA = 1 'poorten A,B en C worden geconfigureerd
TRISB = 1 ' 1 = ingang, 0 = uitgang
TRISC = 0
aansturing van de knoppen
worden knoppen tegenwoordig ook al aangestuurd?
volgens mij worden ze ingelezen...
bedoel je hiermee dat je geen hoog signalen krijgt?
lampjes
...
Wat ik me ook afvraag is het volgende: wanneer een munt voorbij de sensor valt, zal die sensor dan niet te lang een signaal geven (zodat hij er eigenlijk tien ofzo telt)?
start:
dummywaarde = inputsignaal
if dummywaarde != inputsignaal {
dan is de input veranderd, oftewel munt gevallen
}
goto start
Frits Kieftenbelt
Ohm sweet Ohm | www.picbasic.nl
Op 16 maart 2007 20:11:15 schreef wartos:
Waarom niet Jeroen?
Als jij schrijft:
TRISA = 1
TRISB = 1
TRISC = 0...dan betekent dat je door TRISA alleen PORTA.0 een ingang hebt, door TRISB alleen PORTB.0 ingang en alle 8 PORTC poorten zijn uitgangen.
Waarom?
Omdat TRISA = 1 gelijk is aan TRISA = %00000001
Omdat TRISB = 1 gelijk is aan TRISB = %00000001
Omdat TRISC = 0 gelijk is aan TRISC = %00000000
Lees hierover de cursus deel 3: www.picbasic.nl/beginners3_nl.htm