Author Topic: Need help with my first µC project  (Read 8449 times)

0 Members and 1 Guest are viewing this topic.

Offline david77Topic starter

  • Frequent Contributor
  • **
  • Posts: 934
  • Country: de
Need help with my first µC project
« on: September 27, 2010, 09:02:29 pm »
Ok, yesterday I was bored and got the idea to try and get into micorcontrollers again.
I decided on a small project that I've had in mind quite some time now:
A electronic kitchentimer. That shouldn't be too hard to realise.

What I want:
- max. count time: 99 min.
- operation with three buttons: Start/Stop, +1 min., +10 min.

The timer should be able to count from 99 minutes to zero. As display I want to use two 7-segment
diplays. I want to drive them using two BCD-to-7-segment drivers (74LS249) , so I only need 8
I/O ports.
Further I need three I/O's for my buttons, one I/O for a blinking LED to signal the timer is running and
one I/O to activate some sort of buzzer thingy. So 13 I/O lines are enough.

I decided to use an AtMega8L, simply because I had some around and I have a small breadboard for
ATMegas.
I elected BASCOM-AVR to be my language of choice, the reason being: I know BASIC and not much else.

I haven't got a circuit diagram to show you, but it is all rather simple: ATMega8, 2x74LS49, displays and
some buttons and LED's.



And here's my code so far:

Code: [Select]
$regfile = "m8def.dat"                                      ' specify the used micro
$crystal = 4000000                                          ' used crystal frequency
$hwstack = 100                                              ' default use 32 for the hardware stack
$swstack = 100                                              ' default use 10 for the SW stack
$framesize = 100                                            ' default use 40 for the frame space

Config Portd = Output
Config Portc = Output
Config Portd.2 = Input                                      'definiert Portd als Output
Config Portb = Input

Declare Sub Bcdout(byval Mincount As Integer )

Dim Digit1 As Integer , Digit2 As Integer
Dim Mincount As Integer , Seccount As Integer
Dim Sdisplay As String * 2 , Sdigit1 As String * 1 , Sdigit2 As String * 2
Dim Stopped As Integer , Preset As Integer

Let Mincount = 0                                            'Anzeige auf "00" setzen beim einschalte
Let Seccount = 0                                            'Sekundenzähler auf 0 setzen
Let Stopped = 1                                             ' Stopped: 0 = Run / 1 = Stop
                                                             'bei PowerUp soll Zähler stehen

'Config Timer0 = Timer , Prescale = 64
'Enable Timer0
'On Timer0 Isr_pollkeys

Config Timer1 = Timer , Prescale = 256                      'Konfiguriere Timer1
Enable Timer1
On Timer1 Isr_von_timer1                                    'verzweige bei Timer1 ueberlauf zu   Isr_von_Timer1
Timer1 = 49910                                              'Timer auf 49910 setzen (15625 counts = 1sec.)
                                                            '4000000/256=15625 == 1 sec.
Config Int0 = Falling                                       'Konfiguriere INT0 für Start/Stop Taste
Enable Int0
On Int0 Isr_resettaste                                      'Sprung bei INT0 Start/Stop Taste
Enable Interrupts                                           'Interrupts aktivieren



Do                                                          'Hauptprogramm
 If Stopped = 1 Then
  Portc.4 = 1
  Bcdout Mincount
     If Pinb.0 = 0 Then Gosub Inkrement1

 Elseif Stopped = 0 Then
  Portc.4 = 0

  If Seccount = 60 Then
   Let Seccount = 0

   Bcdout Mincount

   If Mincount <> 0 Then
    Let Mincount = Mincount - 1
   Elseif Mincount = 0 Then
    Let Stopped = 1
    Let Mincount = 0
    Let Portc.1 = 1
    Waitms 500
    Let Portc.1 = 0
   End If


  End If

 End If

Loop

End


Inkrement1:
If Stopped = 1 Then Let Mincount = Mincount + 1
If Mincount >= 99 Then Let Mincount = 0

Return


Isr_von_timer1:                                             'ISR von Timer1
 Timer1 = 49910                                             'Timer1 soll wieder von 49910 wegzõhlen
 Let Seccount = Seccount + 1
 Toggle Portc.0
Return


Isr_resettaste:                                             'Reagiert auf Start/Stop Taste
 If Stopped = 1 And Mincount > 0 Then                       'Wenn Stopped=1 und Min-counter > 0 ==STARTTASTE
  Let Stopped = 0                                           'setze Stopped = 0, so dass Zähler laufen kann
 Elseif Stopped = 0 Then                                    'Wenn Stopped = 0 (Zähler läuft) ==STOP/RESET TASTE
  Let Stopped = 1
  Let Mincount = 0                                          'Minutenzähler zurücksetzen
 End If

Return


Isr_pollkeys:
 'If Pinb.0 = 0 Then Gosub Inkrement1
 'Debounce Pinb.0 , 0 , Inkrement1 , Sub
Return




Sub Bcdout(byval Mincount)                                  'SUB gibt BCD Kodiert die Anzeige aus
   Sdisplay = Str(mincount)                                 'Hier wird Minutenzähler (Integer) in String
   If Len(sdisplay) = 1 Then Let Sdisplay = "0" + Sdisplay  'gewandelt, zerlegt, wieder in INT  gewandelt
   Sdigit1 = Left(sdisplay , 1)                             ' und einzeln an die CASE Anweisungen gegeben.
   Sdigit2 = Right(sdisplay , 1)                            'wenn nötig wird eine fuehrende Null angefuegt
   Digit1 = Val(sdigit1)
   Digit2 = Val(sdigit2)

   Select Case Digit1
    Case 1
      Portd.0 = 0
      Portc.3 = 0
      Portc.2 = 0
      Portd.3 = 1
    Case 2
      Portd.0 = 0
      Portc.3 = 0
      Portc.2 = 1
      Portd.3 = 0
    Case 3
      Portd.0 = 0
      Portc.3 = 0
      Portc.2 = 1
      Portd.3 = 1
    Case 4
      Portd.0 = 0
      Portc.3 = 1
      Portc.2 = 0
      Portd.3 = 0
    Case 5
      Portd.0 = 0
      Portc.3 = 1
      Portc.2 = 0
      Portd.3 = 1
    Case 6
      Portd.0 = 0
      Portc.3 = 1
      Portc.2 = 1
      Portd.3 = 0
    Case 7
      Portd.0 = 0
      Portc.3 = 1
      Portc.2 = 1
      Portd.3 = 1
    Case 8
      Portd.0 = 1
      Portc.3 = 0
      Portc.2 = 0
      Portd.3 = 0
    Case 9
      Portd.0 = 1
      Portc.3 = 0
      Portc.2 = 0
      Portd.3 = 1
    Case 0
      Portd.0 = 0
      Portc.3 = 0
      Portc.2 = 0
      Portd.3 = 0
   End Select

   Select Case Digit2
   Case 1
      Portd.4 = 0
      Portd.5 = 0
      Portd.6 = 0
      Portd.7 = 1
    Case 2
      Portd.4 = 0
      Portd.5 = 0
      Portd.6 = 1
      Portd.7 = 0
    Case 3
      Portd.4 = 0
      Portd.5 = 0
      Portd.6 = 1
      Portd.7 = 1
    Case 4
      Portd.4 = 0
      Portd.5 = 1
      Portd.6 = 0
      Portd.7 = 0
    Case 5
      Portd.4 = 0
      Portd.5 = 1
      Portd.6 = 0
      Portd.7 = 1
    Case 6
      Portd.4 = 0
      Portd.5 = 1
      Portd.6 = 1
      Portd.7 = 0
    Case 7
      Portd.4 = 0
      Portd.5 = 1
      Portd.6 = 1
      Portd.7 = 1
    Case 8
      Portd.4 = 1
      Portd.5 = 0
      Portd.6 = 0
      Portd.7 = 0
    Case 9
      Portd.4 = 1
      Portd.5 = 0
      Portd.6 = 0
      Portd.7 = 1
    Case 0
      Portd.4 = 0
      Portd.5 = 0
      Portd.6 = 0
      Portd.7 = 0
   End Select
End Sub

Sorry, the commentary is in German but I reckon it's quite self explaining

PORTC.0: Blinking light, toggles every second
PORTC.4: Is high when counter stopped / low when running. Just for testing
PORTD.0/2 PORTC.1/2 & PORTD.4...7: Output for 2 digits BCD code to 74LS249's
PORTC.1: The output for the buzzy thing.

PIND2/INT0: Start/stop key
PINB.0: Increase 1 min. key

Variables:
Mincount: counter get increased by pressing +1, decreases when timer runs
Seccount: counts the seconds. Gets increased by Timer1 interrupt
Stopped: flag, indicates if counter is running (=0) or stopped (=1)

My problem so far is as follows:
When I compile the program with a pre-set Mincount (maybe 10) then everything works fine.
At this stage I do not read PINB.0.
The counter powers up with "10" on the display. I press "Start" and it counts down to "00", PORTC.1
gets high for a bit and then the thing stops, sets the Stopped flag to 1, the display back to "00".

If, however I add code to read PINB.0 it all goes wrong. The counter increases when the key is pressed
as it should, when I press "Start" the Stopped flag changes, but the counter doesn't count!
It just sits at whatever value I keyed into Mincount.
I tried just polling the key in the main loop (also using DEBOUNCE) and I tried using Timer0 interrupt
to poll the key outside the main loop (the code is there -> Isr_pollkeys:).
The blinking LED on PORTC.0 keeps on blinking, so the Timer1 interrupt seems to work, I guess.

I realise this should be a very simple project, thus I thought I might be able to do it. It is however
my first "real" own µC project, I'm quite a noob here.
Maybe the pro's would choose other hardware or another way to realise it, or choose ASM or C as
language but this is the way I chose to tackle it and I think I can't be that far off. There is probably
something quite obvious I overlook or am not aware of.
Oh, and guys: No BASIC bashing please! I really like that language and I know what the "real" programmers
think of it ;).

So a little nudge in the right direction would be appreciated!

David
 

Offline djsb

  • Frequent Contributor
  • **
  • Posts: 890
  • Country: gb
Re: Need help with my first µC project
« Reply #1 on: September 27, 2010, 09:23:19 pm »
Can you set breakpoints and put watches on the variables that you use to check that they are behaving as you expect?
Have you tried simplifying your program and checking each subroutine one at a time. You could build in some kind of test into the program that uses the LED's as an output (in place of print/printf statements and a serial terminal).

David.
David
Hertfordshire,UK
University Electronics Technician, London PIC,CCS C,Arduino,Kicad, Altium Designer,LPKF S103,S62 Operator, Electronics instructor. Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime. Credited Kicad French to English translator.
 

Offline david77Topic starter

  • Frequent Contributor
  • **
  • Posts: 934
  • Country: de
Re: Need help with my first µC project
« Reply #2 on: September 27, 2010, 10:00:50 pm »
 :-X
Uh, well, the most obvious I didn't see. Ok, thanks David.
I let the display show my Seccount variable and it turned out I didn't put that back to zero when
pressing stop... So the µC never got to the line decreasing my Mincounter.

Now I can ask you guys about another thing that puzzles me. How the hell do I debounce the
switches properly? I want the +1 key to add 1 to the counter each time I press it.
At the moment it's got a mind of it's own...

Do I poll it in the main loop or do I poll it using a Timer0 interrupt every few ms? And if so, how many ms
apart? Or should I use the DEBOUNCE command?
Or should I just whack in some old fashioned hardware debouncing (couple of R's, a C and a 7414)?

So many questions... But I already start to like the µC :).
Some years ago I did a kitchen timer in "discrete" TTL logic...what a pain!

 

Offline PeterG

  • Frequent Contributor
  • **
  • Posts: 830
  • Country: au
Re: Need help with my first µC project
« Reply #3 on: September 27, 2010, 11:57:07 pm »
David,
    i normally de-bounce with a "Delayms 2" or similar command to handle the button bounce. A small cap across the button also helps.

Regards

Peter
Testing one two three...
 

Offline ThoWaBu

  • Newbie
  • Posts: 7
Re: Need help with my first µC project
« Reply #4 on: September 28, 2010, 05:25:37 am »

I think Delay isn´t really a debouncing...

I very short :

In fact of switch prellen there are short "spikes", but you want only count on a minimum KeyPressing Time.

This could be 50ms or something -- it depends on the User interface and how bad the switch is.

So I do the Follow and it works _very_ well :

On switch state Released set your TimeCounter to 0.
On switch state Pressed increase your Counter ervery Timebase.
(Timer interrupt)

If the Counter overruns your Time-Limit (i.e. 50ms) your Key is Pressed.
Don´t let your counter overrun.

You can switch between several Time-Limits to detect long and short pressed Buttons.
(Maybe some overkill)

 

Offline Time

  • Frequent Contributor
  • **
  • Posts: 725
  • Country: us
Re: Need help with my first µC project
« Reply #5 on: September 28, 2010, 02:27:22 pm »
small cap on the switch has ever been all i have needed.
-Time
 

Offline ThoWaBu

  • Newbie
  • Posts: 7
Re: Need help with my first µC project
« Reply #6 on: September 28, 2010, 03:15:09 pm »

@Time :

What Tau do you create by adding a C ?
What Tau is needed to get the SmithTrigger at the Input stage doing well ?
 

Offline nyo

  • Contributor
  • Posts: 46
Re: Need help with my first µC project
« Reply #7 on: September 28, 2010, 05:52:12 pm »
I have successfully used a "delay_ms(100);" for button debounce
Felipe
 

Offline Zero999

  • Super Contributor
  • ***
  • Posts: 19491
  • Country: gb
  • 0999
Re: Need help with my first µC project
« Reply #8 on: September 28, 2010, 06:26:25 pm »
I don't use BASIC but delaying for 10ms is normally more than enough.

A more robust debouncing scheme is to only consider the button to have changed state if it's remained in that state for longer than a given time e.g. 10ms. This is harder to do but it's better because it spikes or induced EMI is less likely to cause false triggering. This can be done using a loop and a timer which is reset every time the switch changes state, if the timer counts down to zero and is not reset then the switch is considered to have settled. I can post some code if you like but it'll either be assembler or pseudo as I don't know PIC BASIC.
 

Offline david77Topic starter

  • Frequent Contributor
  • **
  • Posts: 934
  • Country: de
Re: Need help with my first µC project
« Reply #9 on: September 29, 2010, 01:44:07 pm »
Well. The DEBOUNCE command in BASCOM works quite well actually.
I t didn't work for me because I bollocksed up the port wiring on my bread board.

There's a socket for ATMega16/32 and one for the ATMega8. I wired the pins for PORTB/C/D from the
24pin socket to the ZIF socket and then onto pins where I plug my jump leads in.
It turned out I wired PORTB of the ATMega8 to the pins for PORTA of the ATMega16/32.
As a result my switches were connected to nothing and the PORTB pins I used as inputs were also
connected to nothing. Funnily, the controller reacted to a pressed button. Not in any meaningful and
predictable way, but good enough for me not to notice it sooner.

After correcting my mistake (I just swapped the jump leads to the PORTA pins) it immediately worked,
who'd have thought?

The hard & software for my kitchen timer works now. So it's time to make it into a real product.
This is going to be this years christmas present for various friends and family  :D.

 

Offline Zero999

  • Super Contributor
  • ***
  • Posts: 19491
  • Country: gb
  • 0999
Re: Need help with my first µC project
« Reply #10 on: September 29, 2010, 08:04:28 pm »
Well. The DEBOUNCE command in BASCOM works quite well actually.
Do you know what it actually does though?

Is it a simple time delay or something more complicated as I described above?

If you don't know, then you've found one of the flaws with BAISC: it's too easy so you don't learn as much. If you do know, you can be smug and tell me to shut up.  :P

I'm not meaning to BASIC bash, just make you aware of some of the things it's doing for and that if you let someone wipe your arse for you, you'll never learn to do it yourself. ;)
 

Offline ThoWaBu

  • Newbie
  • Posts: 7
Re: Need help with my first µC project
« Reply #11 on: September 29, 2010, 09:14:01 pm »
I read the BASIC DEBOUNCE does only an double check of state.


Do you have a Scope ?
Please draw the Voltage.
You can read the bounce time and set to an correct value.

With my Algorithm even you can increment your digit faster at longer push...

« Last Edit: September 29, 2010, 09:21:17 pm by ThoWaBu »
 

Offline Zero999

  • Super Contributor
  • ***
  • Posts: 19491
  • Country: gb
  • 0999
Re: Need help with my first µC project
« Reply #12 on: September 30, 2010, 07:20:56 am »
I read the BASIC DEBOUNCE does only an double check of state.

Something like: Is switch (de)pressed? If yes, wait for a certain length of time. Is switch still (de)pressed?

Quote
Do you have a Scope ?
Please draw the Voltage.
You can read the bounce time and set to an correct value.
What about using the MCU to time it?

It shouldn't be hard to write a program to time how long it takes for a switch to settle when it's pressed or released.
 

Offline david77Topic starter

  • Frequent Contributor
  • **
  • Posts: 934
  • Country: de
Re: Need help with my first µC project
« Reply #13 on: September 30, 2010, 07:53:23 am »
Well, I'm aware that BASIC keeps a lot of stuff from me. But I don't really think that's such a bad thing.

I tried my luck with C and have to say it makes my head hurt. There's so much you have to look out for,
especially with variables, memory and how you access it... I honestly can't be bothered with all that.
At least not for simple stuff, I realise there are things where BASIC wouldn't cut the mustard, but hey
I'm happy with a few blinking lights and a few buttons at the moment :D.

I read about debouncing and realise it's not a simple matter to do it properly, I've already made that
experience with hardware debouncing in the past.

Comes time, comes knowledge ;)
 

Offline PeterG

  • Frequent Contributor
  • **
  • Posts: 830
  • Country: au
Re: Need help with my first µC project
« Reply #14 on: September 30, 2010, 08:14:38 am »
I use Crownhills Proton Picbasic for my PIC programming. It lets me use the rapid dev of Basic and also supports inline asm when it is required.
Testing one two three...
 

Offline ThoWaBu

  • Newbie
  • Posts: 7
Re: Need help with my first µC project
« Reply #15 on: September 30, 2010, 07:34:46 pm »
I read the BASIC DEBOUNCE does only an double check of state.

Something like: Is switch (de)pressed? If yes, wait for a certain length of time. Is switch still (de)pressed?

Yes, that´s it !
It´s not bad,
if the time between the measure is high (save) enough.

But our TO set it to a very low value.

Quote
Do you have a Scope ?
Please draw the Voltage.
You can read the bounce time and set to an correct value.
What about using the MCU to time it?

It shouldn't be hard to write a program to time how long it takes for a switch to settle when it's pressed or released.

OK, so do it.
Maybe you can draw down an structure chart, or explain your Algorithm.

How can you predict if it is Low or High ?
The only thing is to measure the High an the Low times.
But how long is the minimun High/low Time ?
If you´re smart enough your Algo will detect an Failure.

I think You need a causality -- You need two things to compare.

But the Only thing you get is :  111111111011101101010000111110000000000011101010010010100101111111111111110000010010101010010101
Package                                :   aaaaaaaaa                      xxxxxbbbbbxxxxxxxxxxxxccc                                 dddddddddddddddxxxxx
My Algo above active high   :    12345678901230120101000012345000000000001230101001001010010123456789ABCDE0000010010101010010101

Package a is 9 times long, sure everyone would say its pushed.
But     b is only 5 is it pushed ? I thing a Statistcal analysis would say yes (conditional probability)
Package c is nothing real...
Package d is E long, it must be a long pushed...
The x could be detected as Low.
Everything between is garbage.

What about switch aging ? The bouncing will increase.
The simplest Method (which are the best) is an increase by a save factor of 2...5 !

In real, i saw switches bouncing up to 120ms !!!!
Thats near to the human speed of reaction.
(And it doen´t took 10ms to push/release a switch)

At the Oszi You can estimate the time you need in statistical fluke and multiply by a save factor.

Next I read this : "I tried just polling the key in the main loop (also using DEBOUNCE) and I tried using Timer0 interrupt
to poll the key outside the main loop (the code is there -> Isr_pollkeys:)."

Correct me if I am wrong.
He executes the Basic-Debounce-Monster (i explain later) inside the InterruptServiceRoutine ?
(I can´t read basic -- I am using C)

When right, he´s doing a very nasty thing !

Debounce WAITS for some time, but the ISR is called every second.
It looks not very critical, but *waiting* for an event must not done in an ISR.

ISR´s should be short as possible, so it don´t overrun.
But waiting is arrrghhh.
This got no name !!!

A non waiting algo is the above one.
It must be in the ISR.
It´s not wasting time by setting flags and increase counters...

Sorry.

Greets
 Thomas


PS: Waiting is never a good thing for a Processor, but in the main loop it´s OK. Maybr sleep mode is good for you ?
« Last Edit: September 30, 2010, 07:53:41 pm by ThoWaBu »
 

Offline david77Topic starter

  • Frequent Contributor
  • **
  • Posts: 934
  • Country: de
Re: Need help with my first µC project
« Reply #16 on: September 30, 2010, 10:29:54 pm »
Thomas,

I have to confess I don't understand most of your post :(, not to worry, that's just me being thick.
The one thing I can say, though, is that I'm not using an interrupt to poll my keys.
The polling of the +/- buttons is done in the main loop with the mentioned DEBOUNCE command.
I do however use INT0 for the start/stop button.

I have understood that the ISR's are to be kept as short as possible.

David
 

Offline ThoWaBu

  • Newbie
  • Posts: 7
Re: Need help with my first µC project
« Reply #17 on: October 01, 2010, 04:44:14 am »


Was für eine Prellzeit hast Du angenommen ?
 

Offline david77Topic starter

  • Frequent Contributor
  • **
  • Posts: 934
  • Country: de
Re: Need help with my first µC project
« Reply #18 on: October 01, 2010, 12:01:43 pm »
Der debounce Befehl wartet standardmässig 25ms. Ich habe mit anderen Werten rumgespielt, unter 10ms
kommt das Prellen dann wieder durch, länger als 25ms hatte keine spürbare Auswirkung.
Kommt ja auch auf die Taster an, im Versuchsaufbau sind's noch andere als ich dann nachher verwende.
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11622
  • Country: my
  • reassessing directives...
Re: Need help with my first µC project
« Reply #19 on: October 01, 2010, 12:43:07 pm »
wow! its getting.... "internationalle"! ;D
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline david77Topic starter

  • Frequent Contributor
  • **
  • Posts: 934
  • Country: de
Re: Need help with my first µC project
« Reply #20 on: October 01, 2010, 12:53:29 pm »
Sorry.

I know it's not polite to speak your mother tongue in company ;).
 

Offline ThoWaBu

  • Newbie
  • Posts: 7
Re: Need help with my first µC project
« Reply #21 on: October 01, 2010, 02:08:17 pm »


Fine,

to be save (in your product :)) you can double this.
The User won´t recognize this delay because he´s to slow...

But why don´t you measure the typical button pushed time, min and max ?
You got an good Hardware setup to do so... ;)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf