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:
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:
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
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?
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.
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.
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!
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.
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.
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
voidread(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
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 */
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:
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.
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.
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
unsignedcharmessung;
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?
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
unsignedcharr_rotate(void){// muss eigentlich l_rotate heissen
2
staticunsignedcharmessung;
3
messung<<=1;// schiebs nach links
4
if(VOUT)messung|=0x01;
5
returnmessung;// 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
unsignedcharread(void)
2
{
3
unsignedcharresult=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
returnresult;
18
}
Ich bin sicher kein Kenner von Codevision, aber auch dieser Compiler
sollte 0 als false definieren und 1 als true.
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
voidanzeige(void)
2
{
3
BCDAnzeige=read();//Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
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
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
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.
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.
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.
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.
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.
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.
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.
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
unsignedcharread(void)
2
{
3
unsignedcharresult=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
returnresult;
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:
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.
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.
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
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/
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.
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:
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.
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?
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.
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.
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
unsignedcharread(void)
2
{
3
unsignedcharresult=0;
4
unsignedchark;
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
returnresult;
20
}
Bringt leider nichts. Es wird immer noch "80" angezeigt.
Wie kann man denn überprüfen ob ein Sensor noch geht?
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;
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...
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?
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.
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.