Forum: Mikrocontroller und Digitale Elektronik Sharp GP2D02 Sensor auslesen mit CodeVisionAVR und einem AT90S8515


von Julian (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich habe hier einen STK200(+) mit einem AT90S8515. Daran habe ich einen 
Sharp GP2D02 Sensor und eine BCD-Anzeige. Ich möchte nun mit dem GP2D02 
eine Entfernung messen, die dann direkt an das Display ausgegeben wird. 
Wenn die Entfernung kleiner als 40cm ist, dann soll eine LED leuchten.
Das ganze in C und in CodeVision.
Ich habe eigentlich keine Ahnung, wie man den Sensor auslesen soll. D.h. 
ich habe nun die Frage, wie man denn jetzt den Sensor ansteuern soll, 
dass dieser mir einen Wert zurück gibt.
Hier ist mal das Datenblatt zum GP2D02: 
http://pdf1.alldatasheet.com/datasheet-pdf/view/42836/SHARP/GP2D02.html

Im Anhang habe ich mal ein Bild von meinem Controller.

Zu den Ports:
Der Sensor ist an Port C
Die Anzeige ist an Port A
LEDs an Port B

Es wäre echt nett von euch, wenn ihr mir helfen könntet. Danke schon mal 
im Voraus!

Ich habe so gut wie kein Code bis jetzt. Ich habe nur mal die Ports 
definiert:
1
////////////////////////////////////////////////////////////////
2
////    Name:       entfernungssensor.c                     ////
3
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
4
////                gemessen und an eine Anzeige            //// 
5
////                ausgegeben. Bei eine Entfernung von     ////
6
///                weniger als 40cm leuchtet eine LED      ////                                   
7
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
8
////                                                        ////
9
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
10
////    Anmerk.:    -                                       ////
11
////                                                        ////
12
////////////////////////////////////////////////////////////////
13
#include <90S8515.h>                //Header-Datei mit controllerspezifischen Abk?rzungen
14
#include <delay.h>                  //Deklarationen
15
16
17
//Bekanntmachund der Methoden
18
void port_init(void);                //Bekanntmachung der Methode port_init
19
//void timer_init(void);               //Bekanntmachung der Methode timer_init 
20
//Vereinbarungen/Deklarationen  
21
                                 
22
23
//Hauptprogramm//
24
25
void main(void)                      
26
{
27
    port_init();                    //Port-Initialisierung 
28
    //timer_init();                   //Timer-Initialisierung
29
    //SREG=0x80;                      //Globale Interrupt Freigabe// Alternativ: #asm("sei")
30
    while (1)
31
    {
32
    }
33
                                        
34
}
35
36
//interrupt[TIM1_OVF] void timer1_ovf_isr(void)
37
//{       
38
//}
39
  
40
41
void port_init(void)
42
{
43
     DDRB=0xFF;                     //Alle Pins am PORTB sind Ausgaenge                                        
44
     DDRD=0x00;                     //Alle Pins am PORTD sind Eingaenge
45
     DDRC=                          //?
46
     DDRA=0xFF;                     //Alle Pins am PORTA sind Ausgaenge                   
47
}
48
49
50
//void timer_init(void)
51
//{
52
//    TCCR1B=0x02;                   //Vorteiler 8->1 Durchlauf 0,131s
53
//    TCNT1H=0x77;                   //Timer Start Wert...
54
//    TCNT1L=0x48;                   //...fuer 70ms setzen
55
//    TIMSK=0x80;                    //Timer1-Overflow-Interrupt freigeben        
56
//}

von Julian P. (jupa1337)


Angehängte Dateien:

Lesenswert?

Hallo,
ich habe hier einen STK200(+) mit einem AT90S8515. Daran habe ich einen
Sharp GP2D02 Sensor und eine BCD-Anzeige. Ich möchte nun mit dem GP2D02
eine Entfernung messen, die dann direkt an das Display ausgegeben wird.
Wenn die Entfernung kleiner als 40cm ist, dann soll eine LED leuchten.
Das ganze in C und in CodeVision.
Ich habe eigentlich keine Ahnung, wie man den Sensor auslesen soll. D.h.
ich habe nun die Frage, wie man denn jetzt den Sensor ansteuern soll,
dass dieser mir einen Wert zurück gibt.
Hier ist mal das Datenblatt zum GP2D02:
http://pdf1.alldatasheet.com/datasheet-pdf/view/42836/SHARP/GP2D02.html
Hier habe ich mal ein Bild von meinem Controller. 
https://imgur.com/a/7TQJsdi

Zu den Ports:
Der Sensor ist an Port C
Die Anzeige ist an Port A
LEDs an Port B

Es wäre echt nett von euch, wenn ihr mir helfen könntet. Danke schon mal
im Voraus!

Ich habe so gut wie kein Code bis jetzt. Ich habe nur mal die Ports
definiert:
1
////////////////////////////////////////////////////////////////
2
////    Name:       entfernungssensor.c                     ////
3
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
4
////                gemessen und an eine Anzeige            //// 
5
////                ausgegeben. Bei eine Entfernung von     ////
6
///                 weniger als 40cm leuchtet eine LED      ////                                   
7
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
8
////                                                        ////
9
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
10
////    Anmerk.:    -                                       ////
11
////                                                        ////
12
////////////////////////////////////////////////////////////////
13
#include <90S8515.h>                //Header-Datei mit controllerspezifischen Abk?rzungen
14
#include <delay.h>                  //Deklarationen
15
16
17
//Bekanntmachund der Methoden
18
void port_init(void);                //Bekanntmachung der Methode port_init
19
//void timer_init(void);               //Bekanntmachung der Methode timer_init 
20
//Vereinbarungen/Deklarationen  
21
                                 
22
23
//Hauptprogramm//
24
25
void main(void)                      
26
{
27
    port_init();                      //Port-Initialisierung 
28
    //timer_init();                   //Timer-Initialisierung
29
    //SREG=0x80;                      //Globale Interrupt Freigabe// Alternativ: #asm("sei")
30
    while (1)
31
    {
32
    }
33
                                        
34
}
35
36
//interrupt[TIM1_OVF] void timer1_ovf_isr(void)
37
//{       
38
//}
39
  
40
41
void port_init(void)
42
{
43
     DDRB=0xFF;                     //Alle Pins am PORTB sind Ausgaenge                                        
44
     DDRD=0x00;                     //Alle Pins am PORTD sind Eingaenge
45
     DDRC=                          //?
46
     DDRA=0xFF;                     //Alle Pins am PORTA sind Ausgaenge                   
47
}
48
49
50
//void timer_init(void)
51
//{
52
//    TCCR1B=0x02;                   //Vorteiler 8->1 Durchlauf 0,131s
53
//    TCNT1H=0x77;                   //Timer Start Wert...
54
//    TCNT1L=0x48;                   //...fuer 70ms setzen
55
//    TIMSK=0x80;                    //Timer1-Overflow-Interrupt freigeben        
56
//}

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

Da steht:

Forum: Projekte & Code

Hier könnt ihr eure Projekte, Schaltungen oder Codeschnipsel vorstellen 
und diskutieren. Bitte hier keine Fragen posten!

Gelesen?

MfG Spess

von H.Joachim S. (crazyhorse)


Lesenswert?

Du hast also bis jetzt exakt NICHTS an Software geschrieben/versucht.
Du hast es nicht mal geschafft, einen konkreten link zu dem Sensor zu 
posten.

Nun ja, kann man so machen und versuchen - ob es viel Erfolg hat?

von Julian P. (jupa1337)


Lesenswert?

Den Link hat es wohl verhauen; Sollte jetzt aber wieder gehen. Hier ist 
der Link nochmal: 
http://pdf1.alldatasheet.com/datasheet-pdf/view/42836/SHARP/GP2D02.html

Wie soll ich einen Code schreiben, wenn ich nicht weiß, wie ich ihn 
ansteuern soll? Versucht habe ich schon einiges aber bis jetzt kam 
nichts vernünftiges bei rum und deshalb melde ich mich ja jetzt hier im 
Forum.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Steht doch in der Timing Chart, ich übersetze das mal:
1. Halte VIN für min. 70ms auf Low, der Sensor macht seine Messung.
2. Takte VIN mit 100µs high und anschliessend 100µs low und lese nach 
der fallenden Flanke den Output - MSB kommt zuerst.
3. Wiederhole das 8 mal.
4. Halte VIN für mindestens 1,5ms high, um den Auslesemodus zu beenden. 
Der Sensor geht in Power Off.

: Bearbeitet durch User
von Julian P. (jupa1337)


Lesenswert?

Matthias S. schrieb:
> Steht doch in der Timing Chart, ich übersetze das mal:
> 1. Halte VIN für min. 70ms auf Low, der Sensor macht seine Messung.
> 2. Takte VIN mit 100µs high und anschliessend 100µs low und lese nach
> der fallenden Flanke den Output - MSB kommt zuerst.
> 3. Wiederhole das 8 mal.
> 4. Halte VIN für mindestens 1,5ms high, um den Auslesemodus zu beenden.
> Der Sensor geht in Power Off.

Okay, danke schon mal.
Aber ich hätte da noch ein paar Fragen:
Wenn Laut Sensor VOUT das Bit 7 ist, dann ist das doch PORTC.7 oder?
Das Gleiche dann für VIN: Bit 4 ist dann PORTC.4?

Wie genau muss ich dann PORTC oder DDRC definieren? Eingänge sind 0 und 
Ausgänge sind 1, also würde das dann bedeuten 0b01111111 also 0x7F?

Der Port C sollte doch 0-Aktiv sein: dann müsste low ja 1; und high ja 0 
bedeuten oder?

Ihr könnt ja mal mein Code anschauen und mir schreiben, was ich falsch 
mache. Danke!
1
////////////////////////////////////////////////////////////////
2
////    Name:       entfernungssensor.c                     ////
3
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
4
////                gemessen und an eine Anzeige            //// 
5
////                ausgegeben. Bei eine Entfernung von     ////
6
///                weniger als 40cm leuchtet eine LED      ////                                   
7
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
8
////                                                        ////
9
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
10
////    Anmerk.:    -                                       ////
11
////                                                        ////
12
////////////////////////////////////////////////////////////////
13
#include <90S8515.h>                //Header-Datei mit controllerspezifischen Abk?rzungen
14
#include <delay.h>                  //Deklarationen
15
16
17
//Bekanntmachund der Methoden
18
void port_init(void);                  //Bekanntmachung der Methode port_init
19
void read(void);                       //Bekanntmachung der Methode read
20
void anzeige(void);                    //Bekanntmachung der Methode anzeige
21
unsigned char r_rotate (unsigned char bitmuster);       //Bekanntmachung der Methode r_rotate 
22
//Vereinbarungen/Deklarationen
23
unsigned char wert;
24
unsigned char bitmuster;
25
int k;                                 
26
27
//Hauptprogramm//
28
29
void main(void)                      
30
{
31
    port_init();                      //Port-Initialisierung 
32
    while (1)
33
    {
34
    read();
35
    }
36
                                        
37
}
38
39
40
void read(void)
41
{
42
    PORTC.4=1;                       //VIN auf low
43
    delay_ms(70);                    //fuer 70ms
44
    for (k=0; k<8; k++)              //wiederhole 8 mal
45
    {
46
        PORTC.4=0;                   //VIN auf high
47
        delay_us(100);               //fuer 100us
48
        PORTC.4=1;                   //VIN auf low
49
        delay_us(100);               //fuer 100us
50
        wert=r_rotate(PORTC.7);      //VOUT auslesen und verwendung der Methode um linkszuschieben
51
    }
52
}  
53
54
unsigned char r_rotate (unsigned char bitmuster)
55
{
56
     bitmuster=bitmuster>>1;        //linksschieben, damit MSB rechts steht
57
     return bitmuster;
58
}
59
60
void anzeige(void)
61
{
62
    PORTA=wert;                     //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
63
}
64
65
void port_init(void)
66
{
67
     DDRB=0xFF;                     //Alle Pins am PORTB sind Ausgaenge                                        
68
     DDRD=0x00;                     //Alle Pins am PORTD sind Eingaenge
69
     DDRC=0x7F;                     //?
70
     DDRA=0xFF;                     //Alle Pins am PORTA sind Ausgaenge                   
71
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Julian P. schrieb:
> PORTC.4=1;                       //VIN auf low

Ich weiss ja nicht, was du da für einen Compiler benutzt, aber eine 1 
bedeutet im Allgemeinen high und eine 0 steht für low.

: Bearbeitet durch User
von H.Joachim S. (crazyhorse)


Lesenswert?

Das ist ja wenigstens mal ein Anfang.
Lass die direkten Ports aus dem Programm, erhöht die Lesbarkeit und 
macht es einfacher, dass später vielleicht mal auf einen anderen 
Port/Pin zu schieben.
#define VIN PORTC.4

.
VIN=0;
.
VIN=1;

Entweder falsch gedacht oder nur der Kommentar falsch?
>PORTC.4=0;                   //VIN auf high

Das ist auf jeden Fall falsch:
>wert=r_rotate(PORTC.7);      //VOUT auslesen und verwendung der
> Methode um linkszuschieben
Gelesen wird nicht von PORTC.7, sondern von PINC.7
Und ob man dafür noch eine extra Funktion verwenden sollte? Kann man 
machen, muss man nicht.

von Julian P. (jupa1337)


Lesenswert?

Matthias S. schrieb:
> Julian P. schrieb:
>> PORTC.4=1;                       //VIN auf low
>
> Ich weiss ja nicht, was du da für einen Compiler benutzt, aber eine 1
> bedeutet im Allgemeinen high und eine 0 steht für low.

Ok. Ich benutze den "CodeVisionAVR C Compiler" also denke ich einen ganz 
normalen C Compiler.
So sieht jetzt meine Methode read() aus aber es funktioniert immer noch 
nichts. Auf dem Display wird immer noch 00 Angezeigt.
1
void read(void)
2
{
3
    PORTC.4=0;                       //VIN auf low
4
    delay_ms(70);                    //fuer 70ms
5
    for (k=0; k<8; k++)              //wiederhole 8 mal
6
    {
7
       PORTC.4=1;                   //VIN auf high
8
        delay_us(100);               //fuer 100us
9
        PORTC.4=0;                   //VIN auf low
10
        delay_us(100);               //fuer 100us
11
        wert=r_rotate(PORTC.7);      //VOUT auslesen und verwendung der Methode um linkszuschieben
12
    }
13
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Julian P. schrieb:
> wert=r_rotate(PORTC.7);      //VOUT auslesen und verwendung der
> Methode um linkszuschieben

Du hast aber schon den Beitrag von crazyhorse gelesen? PORTC auszulesen 
bringt dir gar nichts. Du musst das PINC Register lesen, um den Pegel an 
einem Eingang zu lesen.

Julian P. schrieb:
> bitmuster=bitmuster>>1;        //linksschieben, damit MSB rechts
> steht
>      return bitmuster;

Ausserdem möchten die meisten von uns, das das MSB links steht und auch, 
das der Pin tatsächlich ins bitmuster wandert. Hier mal ein altes 
Konstrukt von mir mit GCC, was sowas macht:
1
bitmuster <<= 1;  /* shift one bit to the left - MSB comes first */ 
2
     if (bit_is_set(PINC,4)) {
3
  bitmuster |= 0x01 ; /* set the lowest data bit */
4
     }

: Bearbeitet durch User
von Julian P. (jupa1337)


Lesenswert?

Okay, nein tatsächlich habe ich den Kommentar überlesen. Danke für den 
Hinweis!! Ich bin tatsächlich ein weinig durcheinander was rechts und 
links angeht aber ich hoffe ich bekomme das dennoch hin.
1
bitmuster <<= 1;  /* shift one bit to the left - MSB comes first */ 
2
     if (bit_is_set(PINC,4)) {
3
  bitmuster |= 0x01 ; /* set the lowest data bit */
4
     }
das mit dem if habe ich nicht ganz verstanden, da es bei mir kein 
"bit_is_set" gibt (Error: C:\Users\vm\Desktop\entfernungssensor.c(62): 
undefined symbol 'bit_is_set')

Meine Anzeige zeigt immer noch 00 an. Wie muss ich den in meiner 
port_init() DDRC definieren? Ist 0x7F richtig?

Hier mal der geupdatete Code:
1
////////////////////////////////////////////////////////////////
2
////    Name:       entfernungssensor.c                     ////
3
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
4
////                gemessen und an eine Anzeige            //// 
5
////                ausgegeben. Bei eine Entfernung von     ////
6
///        weniger als 40cm leuchtet eine LED      ////                                   
7
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
8
////                                                        ////
9
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
10
////    Anmerk.:    -                                       ////
11
////                                                        ////
12
////////////////////////////////////////////////////////////////
13
#include <90S8515.h>                //Header-Datei mit controllerspezifischen Abkuerzungen
14
#include <delay.h>                 
15
#define VIN PORTC.4
16
#define VOUT PINC.7
17
#define LED PORTB
18
#define BCDAnzeige PORTA
19
//Bekanntmachund der Methoden
20
void port_init(void);                  //Bekanntmachung der Methode port_init
21
void read(void);                       //Bekanntmachung der Methode read
22
void anzeige(void);                    //Bekanntmachung der Methode anzeige
23
void warnung(void);                    //Bekanntmachung der Methode anzeige
24
unsigned char r_rotate (unsigned char bitmuster);       //Bekanntmachung der Methode r_rotate 
25
//Vereinbarungen/Deklarationen
26
unsigned char wert;
27
unsigned char bitmuster;
28
int k;
29
int reading=0;                                 
30
31
//Hauptprogramm//
32
33
void main(void)                      
34
{
35
    port_init();                      //Port-Initialisierung 
36
    while (1)
37
    {
38
    read();
39
    }
40
                                        
41
}
42
43
44
void read(void)
45
{
46
    VIN=0;                           //VIN auf low
47
    delay_ms(70);                    //fuer 70ms
48
    for (k=0; k<8; k++)              //wiederhole 8 mal
49
    {
50
        VIN=1;                       //VIN auf high
51
        delay_us(100);               //fuer 100us
52
        VIN=0;                       //VIN auf low
53
        delay_us(100);               //fuer 100us
54
        wert=r_rotate(VOUT);         //VOUT auslesen und verwendung der Methode um linkszuschieben
55
    }
56
}
57
58
59
unsigned char r_rotate (unsigned char bitmuster)
60
{
61
     bitmuster=bitmuster<<=1;        //linksschieben, damit MSB links steht
62
     bitmuster|=0x01;                //setzt das niedrigste Bit
63
     return bitmuster;
64
}
65
66
void warunung(void)
67
{
68
  if (wert<=40)                     //Wenn der Wert also die Entfernung unter 40cm liegt
69
  {
70
    LED=~0x01;                      //dann leuchted die LED an PB.0
71
  }
72
}
73
void anzeige(void)
74
{
75
    BCDAnzeige=reading;             //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
76
}
77
78
void port_init(void)
79
{
80
     DDRB=0xFF;                     //Alle Pins am PORTB sind Ausgaenge                                        
81
     DDRD=0x00;                     //Alle Pins am PORTD sind Eingaenge
82
     DDRC=0x7F;                     //?
83
     DDRA=0xFF;                     //Alle Pins am PORTA sind Ausgaenge                   
84
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Julian P. schrieb:
> bitmuster=bitmuster<<=1;        //linksschieben, damit MSB links
> steht

Das solltest Du Dir nochmal genauer ansehen. In der Zeile stehen gleich 
zwei Zuweisungen.

Rotieren bedeutet außerdem nicht, daß das unterste Bit zwangsweise auf 1 
gesetzt wird.

Wenn man die vier Bits abcd rotiert, sollte nach einem Durchlauf bcda, 
nach dem zweiten cdab, nach dem dritten dabc und nach dem vierten wieder 
abcd herauskommen; bei Dir aber kommt nach dem vierten Durchlauf 1111 
heraus.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Zumal in deinem 'bitmuster' ja VOUT steht, was du als 'PINC.7' 
definierst.
Setz mal PINC.7 statt bitmuster ein und du siehst, das da Unsinn 
rauskommt.

Am sinnvollsten machst du also eine extra Variable für das Ergebnis, in 
das du den Bitzustand von PINC.7 reinschiebst. Ob du da eine static in 
der Unterfunktion nimmst oder die Schleife einfach in die Lesefunktion 
verlegst, ist dabei wurscht.

Julian P. schrieb:
> das mit dem if habe ich nicht ganz verstanden, da es bei mir kein
> "bit_is_set" gibt

Zugegeben, das ist eine antiquierte Funktion aus den alten GCC Zeiten. 
Mir gings eher um die Trennung von Pin und Ergebnisvariable.

: Bearbeitet durch User
von Julian P. (jupa1337)


Lesenswert?

Matthias S. schrieb:
> Am sinnvollsten machst du also eine extra Variable für das Ergebnis, in
> das du den Bitzustand von PINC.7 reinschiebst. Ob du da eine static in
> der Unterfunktion nimmst oder die Schleife einfach in die Lesefunktion
> verlegst, ist dabei wurscht.

Okay, d.h.

ich nehme z.B.
1
unsigned char messung;
und mache dann einfach
1
messung=VOUT;            //VOUT auslesen
und dann hat "messung" entweder den Wert 0 oder 1; diesen schiebe ich 
dann?So?
1
bitmuster=messung << 1;
Oder gibt es eine elegante Lösung um einer Variable 8 Bits nach einander 
zuzuweisen?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Julian P. schrieb:
> Oder gibt es eine elegante Lösung um einer Variable 8 Bits nach einander
> zuzuweisen?

Du kannst doch in meiner o.a. Funktion 'bit_is_set' einfach durch if 
(VOUT) ersetzen.
Also:
1
unsigned char r_rotate(void) {   // muss eigentlich l_rotate heissen
2
static unsigned char messung;
3
messung <<= 1; // schiebs nach links
4
if (VOUT) messung |= 0x01;
5
return messung; // erst nach 8 durchläufen richtig.

Aber sinnvoll ist das nicht so richtig. Besser ist es, den ganzen Kram 
gleich in die Leseroutine zu verlegen. Also :
1
unsigned char read(void)
2
{
3
unsigned char result = 0;
4
    VIN=0;                           //VIN auf low
5
    delay_ms(70);                    //fuer 70ms
6
    for (k=0; k<8; k++)              //wiederhole 8 mal
7
    {
8
        VIN=1;                       //VIN auf high
9
        delay_us(100);               //fuer 100us
10
        VIN=0;                       //VIN auf low
11
        delay_us(100);               //fuer 100us
12
        result <<= 1;                // schiebs nach links
13
        if (VOUT) result |= 0x01;    // setze das niedrigste bit, wenn VOUT high
14
    }
15
    VIN = 1; 
16
    delay_ms(2);
17
   return result;
18
}
Ich bin sicher kein Kenner von Codevision, aber auch dieser Compiler 
sollte 0 als false definieren und 1 als true.

: Bearbeitet durch User
von Julian P. (jupa1337)


Lesenswert?

Danke! Nun, die Übergabe an das Display. Die Methode sollte ja 
eigentlich nach dem die for Schleife beendet ist den Wert result tragen. 
Allerdings zeigt mein Display immer noch 00 an.
1
void anzeige(void)
2
{
3
    BCDAnzeige=read();                 //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
4
}

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Julian P. schrieb:
> Allerdings zeigt mein Display immer noch 00 an.

Ich habe mich gerade mal kurz über Bit Operationen mit Codevision 
belesen:
https://www.avrfreaks.net/comment/26024

Da steht, das du doch mit dem Lesen von PORTC.7 recht hattest, also doch
1
#define VOUT PORTC.7
gültig ist zum Lesen von Bit 7 des Port C. Schreibs also wieder um.

Die Funktion BCDAnzeige ist uns allerdings unbekannt und erwartet sicher 
ein Argument. Es könnte also sein, das sowas wie
1
BCDAnzeige(read());
richtiger wäre.

von Julian P. (jupa1337)


Lesenswert?

Danke für deine viele Hilfe.
Leider zeigt mein Display immer noch 00 an.
Hier nochmal ein Update:
1
////////////////////////////////////////////////////////////////
2
////    Name:       entfernungssensor.c                     ////
3
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
4
////                gemessen und an eine Anzeige            //// 
5
////                ausgegeben. Bei eine Entfernung von     ////
6
///                weniger als 40cm leuchtet eine LED      ////                                   
7
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
8
////                                                        ////
9
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
10
////    Anmerk.:    -                                       ////
11
////                                                        ////
12
////////////////////////////////////////////////////////////////
13
#include <90S8515.h>                   //Header-Datei mit controllerspezifischen Abkuerzungen
14
#include <delay.h>                 
15
#define VIN PORTC.4
16
#define VOUT PORTC.7
17
#define LED PORTB
18
#define BCDAnzeige PORTA
19
//Bekanntmachung der Methoden
20
void port_init(void);                  //Bekanntmachung der Methode port_init
21
unsigned char read(void);              //Bekanntmachung der Methode read
22
void anzeige(void);                    //Bekanntmachung der Methode anzeige
23
void warnung(void);                    //Bekanntmachung der Methode anzeige
24
25
//Vereinbarungen/Deklarationen
26
unsigned char wert;
27
int k;                               
28
29
//Hauptprogramm//
30
31
void main(void)                      
32
{
33
    port_init();                        //Port-Initialisierung 
34
    while (1)
35
    {
36
    read();
37
    }
38
                                        
39
}
40
41
42
unsigned char read(void)
43
{
44
unsigned char result = 0;
45
    VIN=0;                           //VIN auf low
46
    delay_ms(70);                    //fuer 70ms
47
    for (k=0; k<8; k++)              //wiederhole 8 mal
48
    {
49
        VIN=1;                       //VIN auf high
50
        delay_us(100);               //fuer 100us
51
        VIN=0;                       //VIN auf low
52
        delay_us(100);               //fuer 100us
53
        result <<= 1;                //schiebs nach links
54
        if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
55
    }
56
    VIN = 1; 
57
    delay_ms(2);
58
   return result;
59
}
60
61
void warunung(void)
62
{
63
  if (wert<=40)                         //Wenn der Wert also die Entfernung unter 40cm liegt
64
  {
65
    LED=~0x01;                          //dann leuchted die LED an PB.0
66
  }
67
}
68
void anzeige(void)
69
{
70
    BCDAnzeige=(read());                 //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
71
}
72
73
void port_init(void)
74
{
75
     DDRB=0xFF;                        //Alle Pins am PORTB sind Ausgaenge                                        
76
     DDRD=0x00;                        //Alle Pins am PORTD sind Eingaenge
77
     DDRC=0x7F;                        //?
78
     DDRA=0xFF;                        //Alle Pins am PORTA sind Ausgaenge                   
79
}

von H.Joachim S. (crazyhorse)


Lesenswert?

Kann sein dass es da steht, stimmt aber trotzdem nicht. Soll der 
Compiler ahnen, ob man jetzt das Portregister oder den Pin lesen will?
Das sind nun mal unterschiedliche Dinge mit unterschiedlichen 
Ergebnissen

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

H.Joachim S. schrieb:
> Kann sein dass es da steht, stimmt aber trotzdem nicht.

Kann ich dir nicht sagen, bin eben kein Codevision Benutzer. Ich muss 
also glauben, was die AVRFreaks da sagen.

Man sollte mal in Ruhe testen, indem man einfach einen Pin liest und auf 
einem anderen Pin ausgibt. Das sollte nicht so schwierig sein. Erst, 
wenn klar ist, wie man Portpins setzt und liest, ist es sinnvoll, sich 
mit dem Programm weiter zu beschäftigen.
Hier ist jedenfalls das CVAVR Manual, mit dem sich der geneigte Leser 
mal beschäftigen kann:
https://www.uni-due.de/~hl271st/Lehre/SMR/cvavr_manual.pdf
Und da steht wieder, das du doch recht hast. Also PINC.7 ist richtig zum 
Lesen des Pins.

Dämliches Internet - die Hälfte von dem, was man da findet, ist Bockmist 
:-P
Ok, und BCDAnzeige ist einfach nur ein Alias für PORTA. Also sollte 
PORTA = read(); eigentlich klappen.
Entferne auch mal den Schreibfehler in der Funktion warnung(), sollte 
der Compiler eigentlich anmeckern.

: Bearbeitet durch User
von Julian P. (jupa1337)


Lesenswert?

Mir ist aufgefallen, dass es ja auch eventuell schlau wäre die Methode 
anzeige(); irgendwo einbauen, sonst wird die ja nie geladen und es ist 
klar, dass die nie was anzeigt. Das beste wäre doch einfach das in die 
read(); zu schreiben. Ich erhalte nur jetzt so eine nette Warnung
"Linker warning: C:\Users\vm\Desktop\entfernungssensor.c(43): function 
'read' not used in data stack usage calculation due to possible 
recursive calls"

Die BCDAnzeige zeigt immer noch 00 an aber die Methode anzeige wird 
geladen, da ich in diese LED=~0x01; als test hinzugefügt habe und es 
leuchtet nur die LED PB.0. Also so wie es soll. Nur die BCDAnzeige will 
nicht.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Julian P. schrieb:
> Nur die BCDAnzeige will
> nicht.

Was passiert denn, wenn du z.B. mal
1
PORTA = 0x55;
schreibst? Da muss ja dann eine 55 im Display stehen.

von Julian P. (jupa1337)


Lesenswert?

Also nehmen wir einmal an ich schreibe in der main
1
void main(void)                      
2
{
3
    port_init();                       //Port-Initialisierung 
4
    while (1)
5
    
6
    {
7
    PORTA=0x55;
8
    }
9
                                        
10
}
Dann erscheint auf dem Display eine 55.
Habe ich in der Main read();
1
void main(void)                      
2
{
3
    port_init();                       //Port-Initialisierung 
4
    while (1)
5
    
6
    {
7
    read();
8
    }
9
                                        
10
}
und in read()
1
unsigned char read(void)
2
{
3
unsigned char result = 0;
4
    VIN=0;                           //VIN auf low
5
    delay_ms(70);                    //fuer 70ms
6
    for (k=0; k<8; k++)              //wiederhole 8 mal
7
    {
8
        VIN=1;                       //VIN auf high
9
        delay_us(100);               //fuer 100us
10
        VIN=0;                       //VIN auf low
11
        delay_us(100);               //fuer 100us
12
        result <<= 1;                //schiebs nach links
13
        if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
14
    }
15
    VIN = 1; 
16
    delay_ms(2);
17
   return result;
18
   anzeige();
19
}
und ich schreibe in die anzeige()
1
void anzeige(void)
2
{
3
    PORTA=0x55;                 //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
4
}
Dann erscheint auf dem Display auch eine 55.

: Bearbeitet durch User
von H.Joachim S. (crazyhorse)


Lesenswert?

Julian P. schrieb:
> delay_ms(2);
>    return result;
>    anzeige();

Das ist Quark, anzeige() wird nie aufgerufen, da es nach return steht.

void main(void)
{unsigned char sensor;
    port_init();                       //Port-Initialisierung
    while (1)

    {
    sensor=read();
    anzeige (sensor);
    if (sensor <  xx) LED=1;
         else LED=0;
    }

}

Ansonsten:
-du solltest dich vom 90S8515 trennen, Uralt-Chip. Klar, wenn es eine 
einmalige Spielerei ist, kann man den immer noch benutzen
-falls der MC später auch noch irgendwas anderes als messen und anzeigen 
machen soll, wirst du dich mit den Timern beschäftigen müssen. 
Insbesonders die 70ms delay sind dann übel, aber  auch die anderen delay 
sind in der Summe nicht ohne.
Wie gesagt, wenn du sonst nichts zu tun hast, kann man das auch so 
lassen, besser aber sich gar nicht erst dran gewöhnen.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

H.Joachim S. schrieb:
> -du solltest dich vom 90S8515 trennen, Uralt-Chip. Klar, wenn es eine
> einmalige Spielerei ist, kann man den immer noch benutzen

Man kann aufs STK200 aber einen aktuelleren ATMega8515 in den gleichen 
Sockel stecken.

@TE: Bitte poste jetzt mal dein Programm komplett. Irgendwie habe ich 
den Eindruck, das du den Wert gar nicht an PORTA übergibst.

von Julian P. (jupa1337)


Lesenswert?

Matthias S. schrieb:

> @TE: Bitte poste jetzt mal dein Programm komplett. Irgendwie habe ich
> den Eindruck, das du den Wert gar nicht an PORTA übergibst.
1
////////////////////////////////////////////////////////////////
2
////    Name:       entfernungssensor.c                     ////
3
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
4
////                gemessen und an eine Anzeige            //// 
5
////                ausgegeben. Bei eine Entfernung von     ////
6
///        weniger als 40cm leuchtet eine LED      ////                                   
7
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
8
////                                                        ////
9
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
10
////    Anmerk.:    -                                       ////
11
////                                                        ////
12
////////////////////////////////////////////////////////////////
13
#include <90S8515.h>                   //Header-Datei mit controllerspezifischen Abkuerzungen
14
#include <delay.h>                 
15
#define VIN PORTC.4
16
#define VOUT PINC.7
17
#define LED PORTB
18
#define BCDAnzeige PORTA
19
//Bekanntmachung der Methoden
20
void port_init(void);                  //Bekanntmachung der Methode port_init
21
unsigned char read(void);              //Bekanntmachung der Methode read
22
23
//Vereinbarungen/Deklarationen
24
25
unsigned char sensor;
26
int k;                               
27
28
//Hauptprogramm//
29
30
void main(void)                      
31
{
32
    port_init();                         //Port-Initialisierung 
33
    while (1)
34
    {
35
    sensor=read();
36
    BCDAnzeige=sensor;
37
  if (sensor<=40)                         //Wenn der Wert also die Entfernung unter 40cm liegt
38
  {
39
    LED=~0x01;                          //dann leuchted die LED an PB.0
40
  }
41
    }
42
                                        
43
}
44
45
46
unsigned char read(void)
47
{
48
unsigned char result = 0;
49
    VIN=0;                           //VIN auf low
50
    delay_ms(70);                    //fuer 70ms
51
    for (k=0; k<8; k++)              //wiederhole 8 mal
52
    {
53
        VIN=1;                       //VIN auf high
54
        delay_us(100);               //fuer 100us
55
        VIN=0;                       //VIN auf low
56
        delay_us(100);               //fuer 100us
57
        result <<= 1;                //schiebs nach links
58
        if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
59
    }
60
    VIN = 1; 
61
    delay_ms(2);
62
   return result;
63
}
64
65
void port_init(void)
66
{
67
     DDRB=0xFF;                        //Alle Pins am PORTB sind Ausgaenge                                        
68
     DDRD=0x00;                        //Alle Pins am PORTD sind Eingaenge
69
     DDRC=0x7F;                        //?
70
     DDRA=0xFF;                        //Alle Pins am PORTA sind Ausgaenge                   
71
}
Die Anzeige ist immer noch auf 00 aber die LED leuchtet, da der Wert 
wohl unter 40 sein muss.

von H.Joachim S. (crazyhorse)


Lesenswert?

Mega16 geht auch, allerdings auf der anderen 40poligen Fassung.
Ich habe gerade gesehen, dass man das Teil immer noch kaufen kann :-), 
gabs vor 20 Jahren bei einer Präsentation von MSC geschenkt und es 
existierten nur ganz wenige AVR-Typen.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Ok, ich habe jetzt noch mal in meinem alten ASM Programmen nachgeschaut, 
was es mit dem Sensor auf sich hat.
Mein Fehler war, das der Sensor selber OUTPUT anhebt, wenn er soweit 
ist.
Hier mal der Auszug aus dem ASM Programm:
1
;  make a single measurement
2
measure:
3
  cbi  PORTB,Vin        ; start sensor by pulling VIN low
4
  ldi  del,w70msec     ; call wozniaks wait routine 
5
  rcall  wozwait         ; for 70ms delay
6
measa:  sbis  PINB,Vout  ; wait for a high 
7
  rjmp  measa
8
  sbi  PORTB,Vin       ; set VIN high
9
  rcall  w100            ; wait 100µs
10
  cbi  PORTB,Vin       ; set VIN low
11
  clr  result          ; clear the place for the result
12
  ldi  counter,8       ; now clock out
13
measb:  rcall  w100            ; 100µs wait
14
  sbic  PINB,Vout       ; check for high on output line
15
  ori  result,0x01     ; its high, shift in a 1
16
  lsl  result          ; shift left
17
  sbi  PORTB,Vin       ; 
18
  rcall  w100
19
  cbi  PORTB,Vin
20
  dec  counter         ; count down
21
  brne  measb           ; not yet 8 bits
22
  rcall  w100            ; wait 100µs
23
  sbi  PORTB,Vin       ; deactivate
24
        rcall   w2ms            ; and let it rest 
25
  ret
Also:
1. Halte VIN für min. 70ms auf Low, der Sensor macht seine Messung.
2. Warte, bis der Sensor Output auf high zieht und takte einmal VIN mit 
100µs high und 100µs low.
3. Takte VIN mit 100µs high und anschliessend 100µs low und lese nach
der fallenden Flanke den Output - MSB kommt zuerst.
4. Wiederhole das 8 mal.
5. Halte VIN für mindestens 1,5ms high, um den Auslesemodus zu beenden.
Der Sensor geht in Power Off.

: Bearbeitet durch User
von Julian P. (jupa1337)


Lesenswert?

Matthias S. schrieb:
> Also:
> 1. Halte VIN für min. 70ms auf Low, der Sensor macht seine Messung.
> 2. Warte, bis der Sensor Output auf high zieht und takte einmal VIN mit
> 100µs high und 100µs low.
> 3. Takte VIN mit 100µs high und anschliessend 100µs low und lese nach
> der fallenden Flanke den Output - MSB kommt zuerst.
> 4. Wiederhole das 8 mal.
> 5. Halte VIN für mindestens 1,5ms high, um den Auslesemodus zu beenden.
> Der Sensor geht in Power Off.
1
unsigned char read(void)
2
{
3
unsigned char result = 0;
4
    VIN=0;                           //VIN auf low
5
    delay_ms(70);                    //fuer 70ms
6
    if (VOUT==1)
7
    {
8
            VIN=1;                       //VIN auf high
9
            delay_us(100);               //fuer 100us
10
            VIN=0;                       //VIN auf low
11
            delay_us(100);               //fuer 100us   
12
       for (k=0; k<8; k++)              //wiederhole 8 mal
13
        {
14
            VIN=1;                       //VIN auf high
15
            delay_us(100);               //fuer 100us
16
            VIN=0;                       //VIN auf low
17
            delay_us(100);               //fuer 100us
18
            result <<= 1;                //schiebs nach links
19
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
20
        }
21
    }
22
    VIN = 1; 
23
    delay_ms(2);
24
   return result;

Also wenn ich es richtig verstanden habe, dann müsste es doch so 
aussehen. Die Anzeige zeigt keinen Wert an, da der Wert sehr 
wahrscheinlich über 0x99 ist. Somit müsste ich nun das Konvertieren 
starten.
Hier mal ein paar Werte, die ich im Internet gefunden habe:
https://docs.google.com/spreadsheets/d/1BcGZW3ky9fWrDV6F9KvR5Kfz6GdRlXk2HgEJJ3y4N1s/

Also könnte man ja einfach ein Array machen in dem man die Werte in cm 
einträgt und den Sensor Wert einfach -105. Falls der Wert unter 0 ist 
einfach auf 0 setzen:
1
//Vereinbarungen/Deklarationen
2
unsigned char  array [] = {80, 77, 74, 72, 70, 67, 65, 63, 61, 59, 57, 55,
3
                53, 52, 51, 49, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37,
4
        36, 35, 34, 34, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28,
5
        28, 27, 27, 26, 26, 25, 25, 25, 24, 24, 24, 23, 23, 23,
6
        22, 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 20, 19, 19,
7
        19, 19, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17,
8
        16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14,
9
        14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12,
10
        12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11,
11
        11, 11, 10, 10, 10, 10};
12
unsigned char entfernung;
13
unsigned char sensor;
14
int k;                               
15
16
//Hauptprogramm//
17
18
void main(void)                      
19
{
20
    port_init();                         //Port-Initialisierung 
21
    while (1)
22
    {
23
    sensor=read();
24
    entfernung=sensor-105;
25
    if (entfernung<0) {entfernung=0;}
26
    entfernung=array[entfernung];
27
    BCDAnzeige=entfernung;
28
  if (entfernung<=40)                         //Wenn der Wert also die Entfernung unter 40cm liegt
29
  {
30
    LED=~0x01;                          //dann leuchted die LED an PB.0
31
  }
32
    }
33
                                        
34
}
nur dann bekomme ich diesen Fehler "Linker error: global RAM variables 
size: 130 bytes is too large"
Also brauche ich entweder einen besseren Controller oder ich muss meinen 
Code optimieren.

: Bearbeitet durch User
von H.Joachim S. (crazyhorse)


Lesenswert?

du brauchst das array ja auch gar nicht im RAM, nur zum lesen:
flash unsigned char  array []...

Ausserdem: nimm lieber lokale Variablen.
k gehört in die read-funktion. Und warum ist gerade die int??

entfernung und sensor in die main.

entfernung=sensor-105;
    if (entfernung<0) {entfernung=0;}


das tut nicht, was du denkst dass es tun sollte (unsigned char).

Unter Project -> C-Compiler kannst du die Verteilung des RAMs 
einstellen.

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Julian P. schrieb:
> if (VOUT==1)

Da arbeiten wir aber nochmal dran. Wenn VOUT 1 ist, tut er das dadrunter 
- aber wenn nicht, dann springt er drüber weg und Ende Banane.

Besser ist es also mit
1
while (!VOUT) {}; //warte, bis VOUT high (true) wird
zu warten.

von Julian P. (jupa1337)


Lesenswert?

Ich habe jetzt zwar ein Sensor, den ich auslesen kann aber es werden 
keine Werte auf dem Display angezeigt, da ich die Messwerte noch 
umwandeln muss.
Da scheiter ich gerade. Ich versuche einfach die Binär Zahl die mir der 
Sensor (hoffentlich) ausgibt in Dec umzuwandeln, damit ich das Array 
auslesen kann. Wenn ich das gleiche in Java mache klappt alles. Leider 
dies nicht so in C. Hier mal den Wandler, den ich verwende: 
https://www.sanfoundry.com/c-program-binary-number-into-decimal/
1
flash unsigned char  array [] =    {0x80, 0x77, 0x74, 0x72, 0x70, 0x67, 0x65, 0x63, 0x61, 0x59, 0x57, 0x55,
2
                                0x53, 0x52, 0x51, 0x49, 0x47, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x39, 0x38, 0x37,
3
                            0x36, 0x35, 0x34, 0x34, 0x33, 0x32, 0x32, 0x31, 0x31, 0x30, 0x30, 0x29, 0x29, 0x28,
4
                            0x28, 0x27, 0x27, 0x26, 0x26, 0x25, 0x25, 0x25, 0x24, 0x24, 0x24, 0x23, 0x23, 0x23,
5
                            0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x19, 0x19,
6
                            0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
7
                            0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x14,
8
                               0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12,
9
                               0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
10
                            0x11, 0x11, 0x10, 0x10, 0x10, 0x10};
11
unsigned char entfernung;
12
int  num, binary_val, decimal_val = 0, base = 1, rem;                             
13
14
//Hauptprogramm//
15
16
void main(void)                      
17
{
18
    port_init();                         //Port-Initialisierung 
19
20
    while (1)
21
   {
22
        num=1101;
23
      binary_val = num;
24
      while (num > 0)
25
      {
26
          rem = num % 10;
27
          decimal_val = decimal_val + rem * base;
28
          num = num / 10 ;
29
          base = base * 2;
30
      }
31
      
32
        entfernung=decimal_val-105;
33
        if (entfernung<=0)
34
        {   
35
            entfernung=0;
36
        }
37
        else if (entfernung>=150)               //Wenn die Entfernung groesser als 150 ist, dann
38
        {
39
            entfernung=129;
40
        }
41
        entfernung=array[entfernung]; 
42
        BCDAnzeige=entfernung;
43
      if (entfernung<=0x40)                      //Wenn der Wert also die Entfernung unter 40cm liegt
44
      {
45
        LED=~0x01;                             //dann leuchted die LED an PB.0
46
      }                                   
47
    }
48
                                        
49
}
Auf meinem Display erscheint eine "12" dabei sollte eine "80" 
erscheinen. Wo liegt mein Fehler?

: Bearbeitet durch User
von H.Joachim S. (crazyhorse)


Lesenswert?

Was machste denn jetzt wieder für einen Kram?
Die Idee, im array gleich die passenden Werte für BCD-Anzeige abzulegen 
und nicht den Umweg ist richtig. Es gibt nichts weiter umzuwandeln.

sensor=read();
if (sensor < xx)
   LED=1;
   else
       LED=0;    //das wieder ausschalten hast du bisher immer vergessen
if (sensor>=105)
   sensor=sensor-105;
   else
       sensor=0;
anzeige=array[sensor];

mehr isses nicht.

von Julian P. (jupa1337)


Lesenswert?

Es wird immer "10" auf dem Display angezeigt. Die LED an PB.0 leuchtet. 
Somit muss das, was der Sensor ausgibt immer über 150 oder 10010110 
liegen. Das kann nicht sein, da das bei jedem Abstand eintritt. Egal ob 
der Sensor 80cm, 10cm, 40cm, 100cm, oder 0cm vom Objekt weg ist. Hier 
mein Code:
1
////////////////////////////////////////////////////////////////
2
////    Name:       entfernungssensor.c                     ////
3
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
4
////                gemessen und an eine Anzeige            //// 
5
////                ausgegeben. Bei eine Entfernung von     ////
6
///                weniger als 40cm leuchtet eine LED      ////                                   
7
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
8
////                                                        ////
9
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
10
////    Anmerk.:    -                                       ////
11
////                                                        ////
12
////////////////////////////////////////////////////////////////
13
#include <90S8515.h>                   //Header-Datei mit controllerspezifischen Abkuerzungen
14
#include <delay.h>                
15
#define VIN PORTC.4
16
#define VOUT PINC.7
17
#define LED PORTB
18
#define BCDAnzeige PORTA
19
//Bekanntmachung der Methoden
20
void port_init(void);                  //Bekanntmachung der Methode port_init
21
unsigned char read(void);              //Bekanntmachung der Methode read
22
23
//Vereinbarungen/Deklarationen
24
flash unsigned char  array [] =    {0x80, 0x77, 0x74, 0x72, 0x70, 0x67, 0x65, 0x63, 0x61, 0x59, 0x57, 0x55,
25
                                0x53, 0x52, 0x51, 0x49, 0x47, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x39, 0x38, 0x37,
26
                            0x36, 0x35, 0x34, 0x34, 0x33, 0x32, 0x32, 0x31, 0x31, 0x30, 0x30, 0x29, 0x29, 0x28,
27
                            0x28, 0x27, 0x27, 0x26, 0x26, 0x25, 0x25, 0x25, 0x24, 0x24, 0x24, 0x23, 0x23, 0x23,
28
                            0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x19, 0x19,
29
                            0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
30
                            0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x14,
31
                               0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12,
32
                               0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
33
                            0x11, 0x11, 0x10, 0x10, 0x10, 0x10};
34
unsigned char sensor;               
35
36
void main(void)                      
37
{
38
    port_init();                         //Port-Initialisierung 
39
40
    while (1)
41
   {
42
        sensor=read();
43
       if (sensor<=127)                            //Wenn der Wert also die Entfernung unter 40cm liegt
44
      {
45
        LED=~0x01;                             //dann leuchted die LED an PB.0
46
      }
47
        else
48
        {
49
            LED=~0x00;
50
        }
51
        sensor=sensor-105;
52
        if (sensor<=0)
53
        {   
54
            sensor=0;
55
        }
56
        else if (sensor>=150)               //Wenn die Entfernung groesser als 150 ist, dann
57
        {
58
            sensor=129;
59
        }
60
        BCDAnzeige=array[sensor];                             
61
    }
62
                                        
63
}
64
65
66
unsigned char read(void)
67
{
68
unsigned char result = 0;
69
unsigned char k;  
70
    VIN=0;                              //VIN auf low
71
    delay_ms(70);                      //fuer 70ms
72
    while (!VOUT)             //warte, bis VOUT high wird
73
    {
74
            VIN=1;                       //VIN auf high
75
            delay_us(100);               //fuer 100us
76
            VIN=0;                       //VIN auf low
77
            delay_us(100);               //fuer 100us   
78
       for (k=0; k<8; k++)               //wiederhole 8 mal
79
        {
80
            VIN=1;                       //VIN auf high
81
            delay_us(100);               //fuer 100us
82
            VIN=0;                       //VIN auf low
83
            delay_us(100);               //fuer 100us
84
            result <<= 1;                //schiebs nach links
85
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
86
        }
87
    }
88
    VIN = 1; 
89
    delay_ms(2);
90
   return result;
91
}
92
93
void port_init(void)
94
{
95
     DDRB=0xFF;                        //Alle Pins am PORTB sind Ausgaenge                                        
96
     DDRD=0x00;                        //Alle Pins am PORTD sind Eingaenge
97
     DDRC=0x7F;                        //Pin C.7 an DDRC sind Eingaenge und Pin C.6-0 sind Ausgaenge
98
     DDRA=0xFF;                        //Alle Pins am PORTA sind Ausgaenge                   
99
}
Wie ist das eigentlich, eigentlich müsste der Sensor ja immer aus und 
und an gehen und somit misst er kontinuierlich oder nicht?

von H.Joachim S. (crazyhorse)


Lesenswert?

Liest du eigentlich, was man dir schreibt?

Matthias S. schrieb:
> Besser ist es also mit while (!VOUT) {}; //warte, bis VOUT high (true)
> wird
> zu warten.
Du sollst erst warten, bis VOUT H wird, dann erst die Leseorgie starten.

Julian P. schrieb:
> sensor=sensor-105;
>         if (sensor<=0)

du kannst keine unsigned-Variable auf < 0 testen. Sensor sei 104, du 
ziehst 105 ab. Ergebnis ist 0xff (was zwar -1 wäre) aber es wird als 255 
interpretiert (unsigned) und dein Tabellenzugriff läuft ins nirgendwo.

von Julian P. (jupa1337)


Lesenswert?

H.Joachim S. schrieb:
> Du sollst erst warten, bis VOUT H wird, dann erst die Leseorgie starten.
Wird das nicht so geschrieben?
1
 while (!VOUT)             //warte, bis VOUT high wird
2
    {
3
            VIN=1;                       //VIN auf high
4
            delay_us(100);               //fuer 100us
5
            VIN=0;                       //VIN auf low
6
            delay_us(100);               //fuer 100us   
7
       for (k=0; k<8; k++)               //wiederhole 8 mal
8
        {
9
            VIN=1;                       //VIN auf high
10
            delay_us(100);               //fuer 100us
11
            VIN=0;                       //VIN auf low
12
            delay_us(100);               //fuer 100us
13
            result <<= 1;                //schiebs nach links
14
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
15
        }
16
    }

> du kannst keine unsigned-Variable auf < 0 testen. Sensor sei 104, du
> ziehst 105 ab. Ergebnis ist 0xff (was zwar -1 wäre) aber es wird als 255
> interpretiert (unsigned) und dein Tabellenzugriff läuft ins nirgendwo.
Okay, danke.
Jetzt verwende ich ein int aber es wird nun immer "80" auf dem Display 
angezeigt.
Wie ist das eigentlich, eigentlich müsste der Sensor ja immer aus und 
und an gehen und somit misst er kontinuierlich oder nicht?

von H.Joachim S. (crazyhorse)


Lesenswert?

nein.
while (!VOUT);<-
.
.
.
Hat natürlich Potential zum Aufhängen des Programms, wenn der Sensor aus 
irgendeinem Grund eben kein H-Signal liefert. Da müsste dann ein timeout 
rein. Aber erst mal ist das so i.O.

von Julian P. (jupa1337)


Lesenswert?

1
unsigned char read(void)
2
{
3
unsigned char result = 0;
4
unsigned char k;  
5
    VIN=0;                              //VIN auf low
6
    delay_ms(70);                      //fuer 70ms
7
    while (!VOUT);             //warte, bis VOUT high wird
8
            VIN=1;                       //VIN auf high
9
            delay_us(100);               //fuer 100us
10
            VIN=0;                       //VIN auf low
11
            delay_us(100);               //fuer 100us   
12
            for (k=0; k<8; k++)               //wiederhole 8 mal
13
            {
14
            VIN=1;                       //VIN auf high
15
            delay_us(100);               //fuer 100us
16
            VIN=0;                       //VIN auf low
17
            delay_us(100);               //fuer 100us
18
            result <<= 1;                //schiebs nach links
19
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
20
             }
21
    VIN = 1; 
22
    delay_ms(2);
23
   return result;
24
}
Ich hoffe ich hab while (!VOUT); nun richtig implementiert. Es wird 
leider immer noch einfach "80" angezeigt.

von H.Joachim S. (crazyhorse)


Angehängte Dateien:

Lesenswert?

Ui ui, habe mir gerade das Datenblatt nochmal angeschaut. Könnte sein 
dass dein Sensor tot ist.

Und mit dem Auslesen wie es Matthias beschrieben hat stimmt auch was 
nicht, es braucht 8 fallende Flanken, nicht 9.
Und wie es danach weiter geht ist irgendwie auch nicht eindeutig. Kann 
man nach dem LSB direkt in den power off gehen oder muss man den 
eingezeichneten Zinnober veranstalten? Oder ist das nur ein Beispiel für 
eine direkt folgende neue Messung?

Komisches Interface jedenfalls.

von Julian P. (jupa1337)


Lesenswert?

H.Joachim S. schrieb:
> Ui ui, habe mir gerade das Datenblatt nochmal angeschaut. Könnte sein
> dass dein Sensor tot ist.
das wäre natürlich schlecht.


> Und mit dem Auslesen wie es Matthias beschrieben hat stimmt auch was
> nicht, es braucht 8 fallende Flanken, nicht 9.

also wieder so:
1
unsigned char read(void)
2
{
3
unsigned char result = 0;
4
unsigned char k;  
5
    VIN=0;                              //VIN auf low
6
    delay_ms(70);                      //fuer 70ms
7
    while (!VOUT);             //warte, bis VOUT high wird
8
            for (k=0; k<8; k++)               //wiederhole 8 mal
9
            {
10
            VIN=1;                       //VIN auf high
11
            delay_us(100);               //fuer 100us
12
            VIN=0;                       //VIN auf low
13
            delay_us(100);               //fuer 100us
14
            result <<= 1;                //schiebs nach links
15
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
16
             }
17
    VIN = 1; 
18
    delay_ms(2);
19
   return result;
20
}

Bringt leider nichts. Es wird immer noch "80" angezeigt.

Wie kann man denn überprüfen ob ein Sensor noch geht?

von H.Joachim S. (crazyhorse)


Lesenswert?

Naja, wenn da "absolute max. rating" steht, dürften die 5V zuviel 
gewesen sein. Vielleicht hat er deswegen nur nicht funktioniert, ist 
aber nicht kaputt gegangen.

Varianten:
-eine Diode in Reihe, vorzugsweise eine Schottky-Diode. Anode VIN, 
Katode AVR-Pin
-einen kleinen Mosfet oder auch npn benutzen, AVR-Ausgang muss dann 
umgekehrt arbeiten
-den AVR-Ausgang als open-drain benutzen.

init:
PORTC.7=0;  //L ins Portregister, interner pullup aus
DDRC.7=0;   //als Eingang, jetzt also hochohmig, Leitung führt H-Pegel 
durch pullup des Sensors

Ansteuerung:

DDRC.7=1;   //jetzt als Ausgang, L des Portregisters erscheint am Pin
DDRC.7=0;   //Ruhezustand (H)

Es steht auch nirgendwo, wie lange es dauert, bis nach fallender Flanke 
tatsächlich das Datenbit erscheint. So langsam, wie das Interface 
ansonsten arbeitet, kann man fast davon ausgehen, dass der AVR zu 
schnell ist wenn man direkt nach VIN=L einliest.
Also lieber so:

#define DDRC.7 VIN
#define active 1
#define passive 0

VIN=active;
delay_ms (70);
VIN=passive;

die Datenbits zu einem anderen Zeitpunkt lesen:

delay_us (100);
VIN=active;       //fallende Flanke
delay_us (100);   //erst danach lesen
result <<= 1;                //schiebs nach links
if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
VIN=passive;

von Gerhard O. (gerhard_)


Lesenswert?

Wie wäre's denn, wenn vorhanden, Graf Oszillo zu Rate ziehen? Da sieht 
man doch gleich was los ist. Manchmal ist HW Vergleich ungemein 
einsichtsvoll.

Nur meine 2 cents...

von Julian P. (jupa1337)


Lesenswert?

Ich habe leider kein Oszilloskop bei mir und ich denke auch nicht, dass 
ich an meinen STK200(+) eine Diode oder ein Mosfet machen kann 
geschweige denn ich besitze sowas nicht.

H.Joachim S. schrieb:

> #define DDRC.7 VIN
> #define active 1
> #define passive 0

Du meinst das eher, oder?
1
#define VIN DDRC.4

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

H.Joachim S. schrieb:
> Und mit dem Auslesen wie es Matthias beschrieben hat stimmt auch was
> nicht, es braucht 8 fallende Flanken, nicht 9.

Die ASM Routine aus
Beitrag "Re: Sharp GP2D02 Sensor auslesen mit CodeVisionAVR und einem AT90S8515"

ist getestet und läuft mit dem GP2D02. Da sind wirklich ausführliche 
Kommentare dran und es ist auch leicht in C umzuschreiben.

H.Joachim S. schrieb:
> Naja, wenn da "absolute max. rating" steht, dürften die 5V zuviel
> gewesen sein. Vielleicht hat er deswegen nur nicht funktioniert, ist
> aber nicht kaputt gegangen.

Der alte GP2D02 läuft nominell mit 4,4V bis 7V. Max. Rating ist 10V.

von H.Joachim S. (crazyhorse)


Lesenswert?

Naja - bei Julian läuft es eben nicht nicht und das muss ja einen Grund 
haben.

Matthias S. schrieb:
> Der alte GP2D02 läuft nominell mit 4,4V bis 7V. Max. Rating ist 10V.

Ja, Vcc und VOUT.
Aber VIN max. 3V. Steht da zumindest, wahrscheinlich nicht nur zum 
allgemeinen Rätselraten. Und wenn man da nun einen 5V-AVR-Ausgang im 
push/pull-Betrieb ohne weitere Massnahmen drannagelt, sind die 3V eben 
überschritten. Was dann passiert weiss keiner.
Unbeeindruckt davon - glaube ich nicht, dann hätten sie es nicht extra 
reingeschrieben.
Kaputt - gut möglich.
Funktioniert nur nicht - auch möglich.

Das Datenblatt und auch das Interface ist jedenfalls eine Zumutung - 
warum auch immer man so was baut.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.