[Atmel][C] Teller springt spontaan op nul.

Pagina: 1
Acties:

  • Virgil
  • Registratie: November 2001
  • Laatst online: 17-05 20:10

Virgil

We're not alone

Topicstarter
Ik moet een stappenteller bouwen voor school, mbv een microcontroller om meer inzicht te krijgen in de microcontroller. Nu gebruiken we een Atmel Atmega32. En voor het beeld gebruiken we een HD44780 LCD scherm. Het scherm werkt perfect, alle strings die we maar willen kunnen we erop krijgen, en zelfs een scroll mogelijkheid.

Nu is het zo, dat ik de software voor het 'tellen' van de stappen heb geschreven.

En dat is geen moeilijke code.

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 do 
  { 
    if ( !(PINB & 0x80)) // Knop zeven ingedrukt?
       {
                
                    b++;
                    
                    buffer = 0x01;
                        schrijf_instructie();
                    
                    sprintf(str, "%d", b);
                    
                    zet_op_scherm(str); // Zet tekst op LCD
            
            
            do      // Wacht tot knop weer losgelaten wordt.
            {
            } while (!(PINB & 0x80));
        }   
        else
        {
                
                sprintf(str, "%d", b);
                
                buffer = 0x01;
                schrijf_instructie();
                
            zet_op_scherm(str); // Zet string op scherm
            
            do  // Wacht totdat knop 7 weer ingedrukt wordt.
            {
            } while ((PINB & 0x80)); 
        }                           
    } while (1);        // Infinite loop


Heel mooi, hij telt. Erg leuk. Grote mijlpaal in ons project.

Nu het probleem; Ja, hij telt wel. Maar op een 'random' moment, springt de teller gewoon weer op nul.

We dachten dat dit met de 'dender' te maken heeft van de sensor, dit is het echter niet. Want als ik als een ongelovelijke spast ga lopen drukken. Springt hij ook pas na een tijd op nul.

Ik dacht dat het dan aan het geheugengebruik zou liggen. Maar dat is niet logisch, want ik heb voor 'str' 20 array plekken. Oftewel, genoeg ruimte om een 3 cijferig getal in op te slaan lijkt je niet?

Nu zou het kunnen liggen, dat b dus op nul wordt gezet, dat dat in str wordt geschreven waardoor er ' 0 ' op het scherm komt te staan.

Probleem is, waar zou ' b ' nul kunnen worden. Want de enige operatie die ik heb met ' b ' is ' b++ '.

De vraag is dus heel simpel:

Waarom zou de teller 'spontaan' op nul komen te staan? En hoe zou ik dit op kunnen lossen?

De volledige code van de 'stappenteller' staat btw hier.

[ Voor 4% gewijzigd door Virgil op 13-10-2004 16:26 ]

Ik was heel, heeeel vroeger SeRRveR


  • Skinkie
  • Registratie: Juni 2001
  • Laatst online: 09-06-2020

Skinkie

Op naar de 500

zou het misschien de limiet van je integer zijn?

Steun Elkaar, Kopieer Nederlands Waar!


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 20-05 17:44

Super_ik

haklust!

watchdog timer uitgezet?
volgens mij kun je het gedeelte in de if vanaf die else weglaten. k snap niet waarom dit er bij zit eigelijk :?
en buffer = 0x01? wat zet je op 1 :?
contactdender kun je ook voorkomen met een condensatortje aan de pin, maar waarschijnlijk duurt je printf en zet op scherm lang genoeg.
wazige code, optimalisatie zou je code wat makkelijker leesbaar maken denk ik.

voor je lcd kun je handige defines gebruiken:
#define lcd_cmd_clear 0x01
#define lcd_cmd_home 0x02
#define lcd_cmd_off 0x08
#define lcd_cmd_cursor_on 0x0E
#define lcd_cmd_cursor_off 0x0C
#define lcd_cmd_cursor_blink 0x0F
#define lcd_cmd_shift_right 0x06

en dan lcd_command(char commando) is netter als
buffer=commando
doe_lcd_commando.

[ Voor 130% gewijzigd door Super_ik op 13-10-2004 16:49 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • Virgil
  • Registratie: November 2001
  • Laatst online: 17-05 20:10

Virgil

We're not alone

Topicstarter
Watchdog timer, nee die heb ik niet uitgezet. Ben nu de datasheet aan het lezen om te kijken wat de watchdog timer nou precies is, en hoe ik die uit kan zetten.

Waarom zou dat een reden kunnen zijn dat hij steeds terug springt op nul?
volgens mij kun je het gedeelte in de if vanaf die else weglaten. k snap niet waarom dit er bij zit eigelijk :?
en buffer = 0x01? wat zet je op 1 :?
contactdender kun je ook voorkomen met een condensatortje aan de pin, maar waarschijnlijk duurt je printf en zet op scherm lang genoeg
buffer = 0x01; staat in combinatie met schrijf_instructie();

Oftewel, PORTD wordt 0x01, oftewel, het scherm wordt leeggemaakt. :). Staat in de datasheet van het LCD scherm, en dat werkt :)

Want als we dat niet doen, moeten we aangeven waar de cursor neergezet moet worden. ( Meer code = groter programma ). Anders wordt de nieuwe tekst gewoon achter de huidige tekst geplakt ^_^.
voor je lcd kun je handige defines gebruiken:
#define lcd_cmd_clear 0x01
#define lcd_cmd_home 0x02
#define lcd_cmd_off 0x08
#define lcd_cmd_cursor_on 0x0E
#define lcd_cmd_cursor_off 0x0C
#define lcd_cmd_cursor_blink 0x0F
#define lcd_cmd_shift_right 0x06

en dan lcd_command(char commando) is netter als
buffer=commando
doe_lcd_commando.
Thx, voor de tip.

Maar zo goed ben ik niet in C.

lcd_commando(char commando) is gewoon een functie? En als ik bijvoorbeeld neerzet:

code:
1
lcd_commando(char lcd_cmd_clear);


dan cleart ie het scherm?

Dat zou dan worden in mijn code.

code:
1
schrijf_instructie(char lcd_cmd_clear);


:?

[ Voor 42% gewijzigd door Virgil op 13-10-2004 16:57 . Reden: ff zet_op_scherm(...) veranderd in schrijf_instructie(...) ]

Ik was heel, heeeel vroeger SeRRveR


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 20-05 17:44

Super_ik

haklust!

t riekt t een beetje naar huiswerk, maargoed
houd er wel rekenig mee dat commando 0x01 verrekte traag is (1,5 msec ofzo)
commando 0x80 is een stuk sneller en je bent ook thuis, alleen je oude tekens staan er nog,
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <iom16.h>
#include <stdio.h>

// Declaraties globale variabelen.
#define lcd_cmd_clear 0x01
#define lcd_cmd_home 0x02
#define lcd_cmd_off 0x08
#define lcd_cmd_cursor_on 0x0E
#define lcd_cmd_cursor_off 0x0C
#define lcd_cmd_cursor_blink 0x0F
#define lcd_cmd_shift_right 0x06

unsigned int a = 0; // Globale variabele voor de functie vertraging();
unsigned int b = 0;

int integer;
char str[20];


// Declaraties van de functies.

void zet_op_scherm( char *p );    // Functie waarin de daadwerkelijke tekst op het scherm wordt gezet

void initialisatie();             // Functie waarin de atmel geinitialiseerd wordt.

void schrijf_instructie(char commando);        // Functie waarin het LCD scherm in feite gereset wordt.
void schrijf_data(char teken);              // Functie waarin het geheugen van het LCD daadwerkelijk wordt beschreven.

void vertraging();                // Functie die zorgt voor de vertraging.

main()
{
  
  initialisatie();
  
  // Stel LCD functie in.
  schrijf_instructie(0x38);
  
  // Activeer lcd scherm.
  schrijf_instructie(lcd_cmd_cursor_off);
  
  // Clear display.
  schrijf_instructie(lcd_cmd_clear);

  
 do 
  { 
    if (( !(PINB & 0x80))) /* SW7 pressed? */
        {
            b++;
            schrijf_instructie(lcd_cmd_clear);
            sprintf(str, "%d", b);
            zet_op_scherm(str); /* Zend tekst naar de PC */
            
            do      /* Wait until SW7 is released again */
            {
            } while (!(PINB & 0x80));
        }   
    } while (1);        /* Endless loop */  

}

void initialisatie()
{

  DDRD = 0xFF;  // Alle poorten op D, output.
  DDRA = 0xFF;  // Alle poorten op A, output.
  
  DDRB = 0x00;  // Alle poorten op B, input.
  
  PORTD = 0x00; // Laag signaal op alle poorten D.
  PORTA = 0x00; // Laag signaal op alle poorten A.
  
  DDRD = 0x00;  // Maak poort D, input. Om te lezen van het LCD.
  
  vertraging();

}

void vertraging()
{

  while( a < 1500 )
  {
  
    a = a++;
  
  }
  
  a = 0;

}

void schrijf_instructie(char commando)
{

  vertraging();
  
  DDRD = 0xFF;    // Alle poorten D, output.
  
  PORTA = 0x04;   // Van poort a wordt RS = 1, RW = 0, E = 0.
  vertraging();
  
  PORTD = commando; // Poort D wordt gelijk aan buffer.
  vertraging();
  
  PORTA = 0x00;   // Einde transfer, dus poort a wordt laag.

}

void zet_op_scherm( char *p )
{
  unsigned int uiCharpointer = 0; // Wijzer naar karakter.
  
  while( p[uiCharpointer] != '\0' ) // Zolang p[x] nog niet het einde van de string is, voer onderstaande uit.
  {
    schrijf_data(p[uiCharpointer]);                    // Schrijf de data.
    uiCharpointer++;                   // Verhoog uiCharpointer met 1.
  
  }  

}

void schrijf_data(char teken)
{

  vertraging();
  
  DDRD = 0xFF;    // Alle poorten d, output

  PORTA = 0x05;   // LCD Scherm klaar maken om ernaar te schrijven.
  vertraging();
  
  PORTD = teken; // Schrijf de inhoud van buffer naar het scherm.
  vertraging();
  
  PORTA = 0x00;   // Haal LCD van schrijfmodus af.

}

[ Voor 7% gewijzigd door Super_ik op 13-10-2004 17:13 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • Virgil
  • Registratie: November 2001
  • Laatst online: 17-05 20:10

Virgil

We're not alone

Topicstarter
Super_ik schreef op 13 oktober 2004 @ 17:12:
t riekt t een beetje naar huiswerk, maargoed
houd er wel rekenig mee dat commando 0x01 verrekte traag is (1,5 msec ofzo)
commando 0x80 is een stuk sneller en je bent ook thuis, alleen je oude tekens staan er nog,
-code-
Bedankt, dat het een beetje naar huiswerk riekt, is eerder omdat het ging over het verbeteren van de leesbaarheid van de code.

Waar het nu om gaat eigenlijk, waarom die teller steeds op nul springt.

Ik heb nu de vertraging verlengd, ipv van 0 tot 1500, nu naar 2000, en dat gaf in eerste instantie de indruk dat het 'opgelost' was.
Niet dus, de 'sprong naar nul' komt gemiddeld nu iets later.

Was het eerst zo rond de 70, (met uitschieters naar 140 en zelfs 200). Is het nu rond de 400.

Als ik ga tellen tot 200, wordt er zelfs helemaal geen tekst geschreven op het LCD maar dat kan wel kloppen, omdat hij dan waarschijnlijk niet genoeg tijd krijgt om de boel te schrijven.

Ik was heel, heeeel vroeger SeRRveR


  • Sjaaky
  • Registratie: Oktober 2000
  • Laatst online: 22-04 07:04
Kijk eens of je atmega gereset wordt en het programma opnieuw start.

  • Virgil
  • Registratie: November 2001
  • Laatst online: 17-05 20:10

Virgil

We're not alone

Topicstarter
Sjaaky schreef op 13 oktober 2004 @ 17:34:
Kijk eens of je atmega gereset wordt en het programma opnieuw start.
Ik wilde net een reply maken, dat ik denk dat de atmega vastloopt, en dat de watchdog timer hem dan reset.

Ik zal de watchdog nu uitzetten, althans, eerst ff uitzoeken hoe dat te doen. ^_^. Datasheets lezen is nog lastig, maar begin er steeds meer van te snappen. :D

-

C:
1
2
3
4
5
6
7
8
9
10
void watchdog_uitzetten()
{

  // Een logische 1 schrijven naar WDTOE en WDE
  WDTCR = (1<<WDTOE) | (1<<WDE);
  
  // Watchdog uitzetten.
  WDTCR = 0x00;

}


Dit is de code die ik heb gevonden in de datasheet om de watchdog timer uit te zetten. Het probleem is, dat hij zo niet door de compiler komt, en een error geeft dat WDTOE en WDE niet gedefinieerd zijn.

Dit zijn gewoon bitadressen / registeradressen. (Ik weet niet hoe je ze noemen moet).

Iig, het is zo

code:
1
2
3
4
5
bit 0. WDP0   Watchdog prescaler 0
bit 1. WDP1   Watchdog prescaler 1
bit 2. WDP2   Watchdog prescaler 2
bit 3. WDE    Watchdog Enable
bit 4. WDTOE  Turnoff Enable


Om de Watchdog uit te zetten moet dus een logische een geschreven worden naar WDE ( je moet zeker weten dat hij aan staat ??? ) en naar WDTOE.

Ik heb hiervoor zelf bedacht dat dat ook zo zou kunnen:

C:
1
2
3
4
5
6
7
8
9
10
void watchdog_uitzetten()
{

  // Een logische 1 schrijven naar WDTOE en WDE
  WDTCR = 0x18;    // 00011000 is de binaire code.
  
  // Watchdog uitzetten.
  WDTCR = 0x00;   // 00000000 is de binaire code.

}


Hij komt zo dus door de compiler heen, zonder errors of wat. Maar toch wordt hij gereset.

Nu ben ik dus niet zeker of de watchdog echt uitgezet wordt of niet. Ik heb geen verstand van debug programma's dus met breakpoints controleren kan ik niet. En ik zou bij god niet weten hoe ik iets zou kunnen emuleren ^_^.

[ Voor 63% gewijzigd door Virgil op 13-10-2004 17:57 ]

Ik was heel, heeeel vroeger SeRRveR


  • Farmerwood
  • Registratie: September 2004
  • Niet online
code:
1
#include <iom16.h>

Je zegt dat je de Atmega32 gebruikt. Gebruik dan ook de header van de 32. De header van de 16 werkt namelijk niet helemaal goed met de 32. O.a poort C geeft problemen. Dat kan je probleem wel eens oplossen als je poort C gebruikt tenminste.

Paar kleine opmerkingen (over de code):

Die code lijkt trouwens rechtstreeks uit de Getting Started van mijn opleiding te komen. Even brak. Je zit niet toevallig in Arnhem op school? :)

Hier doe je:
code:
1
2
3
4
5
//fout (werkt wel, maar nergens voor nodig)
a = a++;

//goed
a++;


Je gebruikt a alleen in de vertragingsfunctie, maar je declareert hem wel globaal.
Een microcontroller heeft niet zoals een pc 'onbeperkt' geheugen beschikbaar. Leer je direct aan geen geheugen te verspillen.

code:
1
2
3
4
5
6
void vertraging()
{
    unsigned int a = 0;

    for(a = 0; a < 1500 ; a++) ;
}

  • Virgil
  • Registratie: November 2001
  • Laatst online: 17-05 20:10

Virgil

We're not alone

Topicstarter
Farmerwood schreef op 13 oktober 2004 @ 21:28:
code:
1
#include <iom16.h>

Je zegt dat je de Atmega32 gebruikt. Gebruik dan ook de header van de 32. De header van de 16 werkt namelijk niet helemaal goed met de 32. O.a poort C geeft problemen. Dat kan je probleem wel eens oplossen als je poort C gebruikt tenminste.
Ik heb inderdaad al een opmerking gekregen van een klasgenoot, de iom32.h te gebruiken.
Paar kleine opmerkingen (over de code):

Die code lijkt trouwens rechtstreeks uit de Getting Started van mijn opleiding te komen. Even brak. Je zit niet toevallig in Arnhem op school? :)
Ja :P, wie ben jij? :P
Hier doe je:
code:
1
2
3
4
5
//fout (werkt wel, maar nergens voor nodig)
a = a++;

//goed
a++;
Ik zit al vanaf vanochtend 11 uur te kloten met dit ding, en heb al 4 keer de code overnieuw getikt. |:( Normaal doe ik het goed hoor! :D
Je gebruikt a alleen in de vertragingsfunctie, maar je declareert hem wel globaal.
Een microcontroller heeft niet zoals een pc 'onbeperkt' geheugen beschikbaar. Leer je direct aan geen geheugen te verspillen.
Mijn eerste idee was dan ook om a gewoon lokaal te declareren, echter, om de een of andere reden. Komen de tekens niet normaal op het scherm.
code:
1
2
3
4
5
6
void vertraging()
{
    unsigned int a = 0;

    for(a = 0; a < 1500 ; a++) ;
}
Zoiets had ik al, alleen dan in de vorm:

code:
1
2
3
4
5
6
7
void vertraging()
{
     int a = 0;
     while( a <= 2000)
        a++;

}

Maar nu als ik "test" weg zou willen schrijven, dan krijg ik niet "test" op het beeldscherm, maar rare ascii tekens.

[ Voor 7% gewijzigd door Virgil op 13-10-2004 23:24 ]

Ik was heel, heeeel vroeger SeRRveR


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 20-05 17:44

Super_ik

haklust!

wacht dan ook gewoon op de busy flag :)
hup, de datasheets in duiken jij! :P

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • Farmerwood
  • Registratie: September 2004
  • Niet online
[...]
Ja :P, wie ben jij? :P
* Farmerwood is momenteel een half jaar op stage. Zit nu in eerste helft van 3de jaar.

Tip: Zoek ff paar lui uit een hogere klas op en vraag die om voorbeeldcode. Dit moet elk jaar gedaan worden en iemand uit mijn klas heeft tevens een goeie driver voor dat display geschreven met alle benodigde functies. Die is intussen bij alle klassen wel bekend en gebruikt. :)

  • Virgil
  • Registratie: November 2001
  • Laatst online: 17-05 20:10

Virgil

We're not alone

Topicstarter
Het probleem lijkt zich opgelost te hebben. Het probleem was dat de interne oscillator in de atmel op een te hoge snelheid draaide. Het probleem is dus, dat het programma sneller '
b++ ' deed, en zoveel instructies naar het scherm stuurde tegelijk. Dat het lcd het niet aankan. (oid). Het programma crasht dus, en de watchdog timer reset hem.

Ik was heel, heeeel vroeger SeRRveR

Pagina: 1