Forum: Mikrocontroller und Digitale Elektronik 90S2313 zu langsam ??


von Chris (Gast)


Lesenswert?

Hallo Leute
Ich programmiere in Basic und habe einen 90S2313 -10 MHz
Nun mein Problem als eingang habe ich ein Low Signal das 100 ms lang
ist und nun schaltet der Ausgang oft und oft auch wieder nicht !!
Also absolut unzuverlässig . Als Quarz habe ich 8 MHz. Sind denn 100 ms
zu wenig ?? nicht oder !!

Wo liegt mein fehler hier mein Listing.

$regfile = "2313def.dat"
$crystal = 7372800
Ddrb = 255 : Portb = 0
Dim A As Byte
Dim B As Byte
Do

Debounce Pind.0 , 0 , Kanal1 , Sub

Loop
Kanal1:
For A = 1 To 1
      Portb.0 = 1
      Wait 5
      Portb.0 = 0
      Waitms 150
Next
Return

von Nik Bamert (Gast)


Lesenswert?

hi!


>For A = 1 To 1
>      Portb.0 = 1
>      Wait 5
>      Portb.0 = 0
>      Waitms 150
>Next

wieso 1 to 1??
entweder führt der uc die befehle erst gar nich aus, weil a zu beginn
schon 1 ist, und ja bei 1 enden soll, oder de uc führt die befehle
einmal aus, dann kannst du for...next aber gleich weglassen.

Nik

von ThomasB (Gast)


Lesenswert?

Hi Chris:
Nur so eine Idee von mir,
Versuch´s mal mit dem Int0 oder Int1.
zb:
$regfile="2313def.dat"
$crystal=xxxxusw
ddrb=255:portb=0
config int0 oder Int1=rising oder falling
on int1 kanal1
enable int1
enable Interrupts
do
loop
kanal1:
'hier steht das Prog.. usw
return
Wie schon gesagt,nur so eine Idee ;-)

von Chris (Gast)


Lesenswert?

Hallo ThomasB Danke erstmal werde ich morgen gleich testen .
Ich geb dann bescheid ob es geht.

Hallo Nik Bamert Danke stimmt ist ein umweg geht aber trotzdem auch so
den ursprünglich lautet das listing so

>For A = 1 To 3
>      Portb.0 = 1
>      Wait 5
>      Portb.0 = 0
>      Waitms 150
>Next

hab es dann nur schnell zu eins gemacht weil eben die 100 ms als impuls
nicht jedesmal funktionieren.

Soll mal ein entschäumer für mein Seewasser Aquarium werden.
der impuls geht leider nicht länger da es ein durchflußmengenmesser
ist.

Danke bis Morgen

von Frank Linde (Gast)


Lesenswert?

Hallo Chris,

so als BASCOM-Laie frage ich mich, warum Du bei einem 8 MHz Quarz das
hier schreibst:

$crystal = 7372800

Ich hätte jetzt

$crystal = 8000000

erwartet, aber wie gesagt, ich habe keine Ahnung von BASCOM.

Gruß, Frank

von Peter D. (peda)


Lesenswert?

Das kann garnicht gehen.

Du wartest ja  3 * (5 + 150)ms = 465ms.

Dann kannst Du doch nicht erwarten, das zwischendurch alle 100ms ein
Port abgefragt wird.

Warten heißt immer Nichtstun, also CPU-Zeit vergeuden !

Eine Abhilfe gegen das Warten habe ich hier beschrieben:

http://www.mikrocontroller.net/forum/read-4-49709.html

Ist aber in C.


Peter

von Frank Linde (Gast)


Lesenswert?

Mit dem Warten = CPU-Zeit vergeuden hast Du natürlich recht.

In diesem speziellen Fall wäre aber noch wichtig zu erfahren, wie lang
die Zeit zwischen den Eingangsimpulsen ist. Wenn die Zeit im
Unterprogramm kürzer ist, sollte es trotzdem funktionieren. Allerdings
vermute ich, daß Deine Rechnung noch überaus positiv ausgefallen ist,
weil es einmal "Wait" (Einheit vermutlich Sekunden?) und einmal
"Waitms" heißt. Das wären dann bei drei Durchläufen schon 15.450 ms
...

Gruß, Frank

von Chris (Gast)


Lesenswert?

Hallo Danke erstmal für die viele Hilfe .

Also Thomas leider hats auch so nicht geklappt habe alles
durchprobiert.

Hallo Peter Dannegger mit c kann ich leider so gut wie nichts anfangen
(bin ich zu blöd).
Habe leider nur Basic kentnisse ! bin aber schon am überlegen
ob ich nicht wirklich c lernen sollte.

Aber warten tut er doch nur nachdem der schaltbefehl ausgeführt wurde
also müsste es doch auch in basic eine möglichkeit geben das man einen
eingangsport unter 100 ms abfragen kann . Oder ???

Viele Grüsse
Christian

von Peter D. (peda)


Lesenswert?

@Chris,

Wenn das Problem schon vor den 15,45s auftritt, dann liegts wohl nicht
daran, sondern am "debounce"

Was aber nun in der Blackbox "debounce" passiert, das wissen nur die
Bascom-Götter.

Das ist auch der Hauptgrund, warum ich mit Bascom nicht warm werde.
Man schiebt nur "schwarze Kästchen" zusammen ohne zu wissen was darin
passiert und welche Seiteneffekte auftreten (z.B.
Programmverzögerung).

Größere Programme kann man aber so nicht aufbauen.


Aus dem gleichen Grund benutze ich auch nicht Pavels Codevision. Da
sind z.B. alle 1-Wire-Funktionen direkt im Compiler vermanscht.

Es ist aber unmöglich 100% sichere und für jeden denkbaren Fall
optimale Bibliotheken zu erstellen. Deshalb verwende ich grundsätzlich
nur Bibliotheken, die als Sourcetext vorliegen, damit ich eine
Fehlersuche und -Korrektur bzw. Anpassung und Laufzeitabschätzung
selber machen kann.


Peter

von Chris (Gast)


Lesenswert?

Hallo Peter
Danke ich glaube auch das es schon beim Befehl debounce fehlen muß,
bin aber jetzt auch der meinung wenn man listings erstellt die schnelle
abarbeitung brauchen mit Basic (Bascom AVR) nicht sehr weit kommen
wird. Kannst Du mir einen Tip geben wie ich c am besten lernen kann ??
(welches Buch oder so) Danke Peter

An alle BASCOM AVR  Profis !

Hat denn von den Bascom AVR Profis unter euch noch niemand so ein
problem gehabt ??
Oder bin ich da mit meinem listing auf dem falschen weg ??

Gruß
Christian

von Gerhard (Gast)


Lesenswert?

Hay Chris
Hab mich jetzt auch damit beschäftigt, aber im Bascom scheint das
wirklich nicht so zu funktionieren.
Ich kann Dir da nur assembler ans herz legen.( Nicht C )

Gruß
Gerhard

von Gerhard Humer (Gast)


Lesenswert?

Hi Chris,

mit dem wait Befehl darf man das nicht machen!!!!
Der AVR kann in dieser Zeit sonst nichts erledgen.
(kein Multitasking !)
Dazu musst du einen Timer verwenden.

1/10s das sind sogar für Bascom Welten.
Was soll denn nun genau geschehen wenn das Eingangssignal
kommt?
Aus deinem Programm kann ich lesen daß dann ein Ausgangs-pin
5s lang High Pegel führen soll.
Wenn das so richtig ist , würde ich das so machen:

1. In der Do Loop Schleife den Eingang abfragen ,
oder falls noch frei Int0 od. Int1 dazu verwenden.

2. Beim Eingangs-Low-Signal dann den Ausgang setzen ,einen Timer
starten und bei jedem Timerüberlauf eine Variable hochzählen und
abfragen,
bis die 5s erreicht sind. Dann den Ausgang rücksetzen, u. Variable
auf 0 setzen.

Versuch es mal.

Ich kann nur sagen dass ich bisher mit Bascom alles geschafft habe
was ich mir vorgenommen hab.
Sind mal wirklich zeitkritische Sachen zu Programmieren so sind diese
Programmteile halt in Assembler zu schreiben.
Assemblercode ist innerhalb Bascom ja möglich.



Gruss Gerhard

von Chris (Gast)


Lesenswert?

Hallo Gerhard
Das hört sich gut an, könntest Du mir da mal ein beispiel posten.

Hier nochmal was passieren soll.
So soll das fertige Programm mal aussehen ich hatte bisher nur einen
eingang genommen zum testen.

Pind0 ist eingang für low signal 100ms
Pind1 ist eingang für low signal 100ms
Pind2 ist eingang für low signal 100ms

WENN PIND0 oder PIND1 oder PIND2 low signal bekommt soll

Pinb0 ist ausgang high soll 300ms high werden.

Pinb1 ist ausgang high soll 300ms high werden 300ms low wieder 300ms
high und dann low.

Pinb2 ist ausgang high soll 300ms high werden 300ms low wieder 300ms
high und dann wieder 300ms low wieder 300ms high und dann low


das heißt
Pinb0 gibt einen high impuls von 300 ms aus
pinb1 gibt zwei high impulse von 300 ms aus
pinb3 gibt drei high impulse von 300 ms aus

im beispiel habe ich die 5 sec. nur genommen um besser sehen zu können
ob der ausgang schaltet.

Vielen Dank im voraus
Chris

von Sven A. (Gast)


Lesenswert?

Hallo Chris,
versuchs mal hiermit:


$Crystal = 8000000

Config portd = Input
Config portb = output
Portd = 00000111

dim a as byte


do
if pind.0 = 0 or pind.1 = 0 or pind.2 = 0 then
waitms 99
if pind.0 = 0 or pind.1 = 0 or pind.2 = 0 then
gosub impulse
end if
end if
loop


impulse:

set pinb.0
set pinb.1
set pinb.2
waitms 300
reset pinb.0
reset pinb.2
reset pinb.3
waitms 300
set pinb.2
set pinb.3
waitms 300
reset pinb.2
reset pinb.3
waitms 300
set pinb.3
waitms 300
reset pinb.3

return

Hoffe, das klappt.


Sven A.

von Chris (Gast)


Lesenswert?

Hay Sven Danke das könnte so klappen.
Ich werde es nach dem essen gleich mal probieren.

Hast mich aber falsch verstanden wenn

Pind0 ist eingang soll nur Pinb0 einen high impuls ausgeben.
Pind1 ist eingang soll nur Pinb1 einen high impuls ausgeben.
Pind2 ist eingang soll nur Pinb2 einen high impuls ausgeben.

aber zum test werde ich es dann gleich probieren ich gebe Dir dann
bescheid.

Danke
Gruß
Chris

von Sven A. (Gast)


Lesenswert?

Hallo Chris, achso....
na dann


$Crystal = 8000000
Config portd = Input
Config portb = output
Portd = 00000111
dim a as byte
do
if pind.0 = 0 or pind.1 = 0 or pind.2 = 0 then
waitms 99
if pind.0 = 0 then gosub impuls1
if pind.1 = 0 then Gosub Impuls2
If pind.2 = 0 then Gosub Impuls3
end if
end if
loop
impuls1:
set portb.0
waitms 300
reset portb.0

Return

Impuls2:
a = 0
for a = 0 to 1
set portb.1
Waitms 300
reset portb.1
waitms 300
next a

return

impuls3:

a = 0
for a = 1 to 2
set portb.3
waitms 300
reset portb.2
waitms 300

return

sooo, hatte auch ausversehen set Pinb.. usw geschrieben, das
Funktioniert natürlich nicht, aber so sollte das jetzt klappen.


Gruß

Sven A.

von Michael von Gersdorff (Gast)


Lesenswert?

Hallo Chris

Ich wollte einfach nicht glauben daß der Bascom debounce Befehl nicht
geht und ich hatte bei den Listings der Kollegen Fehlermeldungen.
Der beigefügte Code macht glaube ich das was Du möchtest.
Der Debounce Befehl funktioniet tadellos und erlaubt noch die
entsprechende Routine anzuspringen.
Habe keinen 2313 an der Hand daher den 90S8515 genommen und ihn auf das
STK500 gesteckt.

Viel Spaß

Michael


$regfile = "8515DEF.DAT"


Config Portd = Input                                        'Hier sind
die Tasten angeschlossen
Config Portb = Output                                       'hier sind
LEDs angeschlossen

Config Debounce = 1



Do
Debounce Pind.0 , 0 , Erster , Sub
Debounce Pind.1 , 0 , Zweiter , Sub
Debounce Pind.2 , 0 , Dritter , Sub
Loop



Erster:
Set Portb.0
Waitms 300
Reset Portb.0
Return


Zweiter:
Set Portb.1
Waitms 300
Reset Portb.1
Waitms 300
Set Portb.1
Waitms 300
Reset Portb.1
Return


Dritter:
Set Portb.2
Waitms 300
Reset Portb.2
Waitms 300
Set Portb.2
Waitms 300
Reset Portb.2
Waitms 300
Set Portb.2
Waitms 300
Reset Portb.2
Return


End                                                         'end
program

von Peter D. (peda)


Lesenswert?

Man muß bei einer solchen Art Programmierstil aber immer
berücksichtigen, daß Warten auch wirklich absolutes Nichtstun bedeutet
!

D.h. solange die 1,5s "Dritter" ablaufen, kann nichts anderes gemacht
werden.
Dann werden sämtliche anderen Tastendrücke ignoriert und auch
"Dritter" läuft nicht nochmal los, wenn man innerhalb der 1,5s
nochmal gedrückt hat.


Peter

von Michael von Gersdorff (Gast)


Lesenswert?

Hallo Peter

Natürlich hast Du recht und ich würde es so für mich selbst nicht
programmieren da der Prozessor für sonst nichts mehr genutzt werden
kann. Ich wollte eigentlich nur wissen ob der "debounce Befehl einen
"bug" hat was aber nicht der Fall ist.
Ich würde einen der Timer verwenden und diesen beispielsweise immer
wieder für 1 msec zählen lassen sozusagen als Uhr. Paralell dazu würde
ich den drei Eingängen je eine Variable zuweisen und diese dann immer
wenn der Timer seinen Überlauf ereicht (interruptgesteuert)
Inkrementieren bzw Dekrementieren. Damit könnten alle drei Eingänge
unabhängig voneinander funktionieren und die gesamte
Prozessorauslastung wäre vermutlich unterhalb eines Prozents.
Das zu Schreiben und zu Testen dauert aber mehr als 10 Minuten und ich
bin mit eigenen Projekten gut ausgelastet.
Ok?

Gruß
Michael

von Sven A. (Gast)


Lesenswert?

Hallo Michael,

hast recht, hab natürlich 2 schreibfehler drin und einen Befehl noch
vergessen::


$crystal = 8000000


Config portd = Input


Config portb = output

Portd = 00000111


dim a as byte

do
if pind.0 = 0 or pind.1 = 0 or pind.2 = 0 then
waitms 99
if pind.0 = 0 then gosub impuls1
if pind.1 = 0 then Gosub Impuls2
If pind.2 = 0 then Gosub Impuls3
end if

Loop
'************************************************

impuls1:

set portb.0
waitms 300
reset portb.0
Return

'************************************************


Impuls2:
a = 0
for a = 0 to 1
set portb.1
Waitms 300
reset portb.1
waitms 300
next a
return

'************************************************


impuls3:
a = 0
for a = 1 to 2
set portb.3
waitms 300
reset portb.2
Waitms 300
Next A

return


aber so sollte das jetzt gehen, bei deinem Programm müßte im übrigen
Config debounce = 100 stehen, für die 100ms wartezeit, ich benutze den
debounce befehl aber nur , wenn ich taster angeschlossen habe.
Chris benutzt glaube ich einen Durchflußmengen Messer, deshalb.
Für mich würde ich das auch anders Programmieren , aber es sollte ja
auch nur ein Anstoß sein, klar, viele Wege führen nach Rom ;-))


Sven A.

von Peter D. (peda)


Lesenswert?

@Michael,

"die gesamte Prozessorauslastung wäre vermutlich unterhalb eines
Prozents"

stimmt, d.h. der 90S2313 ist definitiv nicht zu langsam, sogar ein
32kHz Quarz müßte reichen.


"Das zu Schreiben und zu Testen dauert aber mehr als 10 Minuten"

Unter Nutzung meines Schedulers habe ich nicht mehr als 10min
gebraucht.

Nachfolgend der Code (leider in C), falls es doch erwünscht ist, daß
alle 3 Tasten unabhängig voneinander funktionieren sollen.
Die Scheduler-, Getkey- und Timerroutinen aus der Codesammlung müssen
noch dazugelinkt werden.


Peter


#include "main.h"

char count0, count1, count2;


void light0_toggle( void ){
  LED_OUTPUT ^= 1<<LED0;                        // LED toggle
  if( --count0 )                                // count down
    timeradd( light0_toggle, SECONDS( 0.3 ));   // toggle time
}


void light1_toggle( void ){
  LED_OUTPUT ^= 1<<LED1;
  if( --count1 )
    timeradd( light1_toggle, SECONDS( 0.3 ));
}


void light2_toggle( void ){
  LED_OUTPUT ^= 1<<LED2;
  if( --count2 )
    timeradd( light2_toggle, SECONDS( 0.3 ));
}


int main( void )
{
  TCCR0 = 1<<CS02;                      //divide by 256 * 256
  TIMSK = 1<<TOIE0;                     //enable timer interrupt

  DDRB = 0xFF;                          // enable outputs
  LED_OUTPUT = 0xFF;                    // all LEDs off

  timerinit();
  sei();

  for(;;){                              // main loop
    if( f_timer_tick ){
      f_timer_tick = 0;
      timertick();                      // run scheduler
    }
    if( get_key_press( 1<<LED0 ) && count0 == 0 ){
      count0 = 2;
      light0_toggle();
    }
    if( get_key_press( 1<<LED1 ) && count1 == 0 ){
      count1 = 4;
      light1_toggle();
    }
    if( get_key_press( 1<<LED2 ) && count2 == 0){
      count2 = 6;
      light2_toggle();
    }
  }
}

von Chris (Gast)


Lesenswert?

Hallo vielen dank für die Super Hilfe.

Hallo Peter danke so funktioniert es 100% und auch wenn während einer
ausführung ein schaltbefehl kommt funktioniert es .
Danke ich werde doch mal versuchen c zu lernen.

Danke auch Sven und Michael auch Eure listings funktionieren
einwanfrei, solange während der ausführung eines schaltbefehls kein
neuer kommt. Aber ich habe wieder etwas dazugelernt.

Danke für Euere Hilfe
Chris

von Sven A. (Gast)


Lesenswert?

Hallo Chris,

schön, das wir dir helfen konnten, brauchst aber deshalb nicht gleich c
zu lernen,das geht mit bascom natürlich auch, stichwort auch, einen
Timer benutzen.


Gruß

Sven

von Chris (Gast)


Lesenswert?

Hallo Sven

Meinst Du wirklich das, das im Bascom das auch gehen würde ??
Ich habe bestimmt 100 möglichkeiten probiert habs aber nicht
geschafft.
Denn immer wenn ein befehl ausgeführt wurde, wurde der eingang
übersehen.
Wenn Du aber noch eine Idee hast gib mir bescheid hab nähmlich die
Test schaltung noch vor mir liegen.
Absolut perfektiert hab mir sogar mit einem 555 einen 100ms impulsgeber
gebaut usw....


Bin also weiter zum Testen bereit.

Gruß Chris

von Peter D. (peda)


Lesenswert?

@Sven,

"brauchst aber deshalb nicht gleich c zu lernen"

Hui, böses Foul :-)

Ich denke mal, daß so eine Enscheidung auf keinen Fall schlecht sein
kann.
Bei kleinen Programmen mag man ja mit Assembler oder Bascom noch den
Überblick behalten.
Aber ATMega128 Programme habe ich bisher nur ausschließlich in C
gesehen (MP3, FAT32, Ethernet usw.)
Spätestens ab ATMega16 braucht man einfach die Leistungsfähigkeit und
Strukturierbarkeit von C, sonst programmiert man sich nen Wolf.



@Chris,

klingt so, als hättest Du mein Programm ausprobiert.
Hast Du den schon den WINAVR installiert und es damit compiliert ?


Peter

von Chris (Gast)


Lesenswert?

Hallo Peter ja ich hab den WinAvr installiert, habs aber nicht geschafft
den surce zu compilieren.
Ein bekannter 600 km entfernt hats mir dann compiliert und den fertigen
hex per e-mail geschikt.
Den hab ich dann eingespielt und Top es geht.
Danke nochmal
Aber was mache ich da falsch im WinAVR mein bekannter kennt sich damit
leider auch nicht aus er benutzt den kostenplichtigen ICC AVR .
Ich habe es nicht geschafft im WinAVR

Gruß
Chris

von Sven A. (Gast)


Lesenswert?

Hallo Chris,
klar, müßte mit Bascom Klappen.

einfach den timer0 nehmen, dann springt das programm automatisch in die
Timer ISR, und da fragst du dann halt deine Eingänge ab.
So könntest du zum Beispiel dann ein Flag setzten, wenn in einer
Befehlsausführung dann ein anderer Eingang angesprochen werden sollte.
Allerdings würde ich dann auch noch eine Variable in der TimerISR
hochzählen, und die dann in der Befehlsausführung nehmen anstatt waitms
.....

Vielleicht kommst du ja damit weiter

Gruß

Sven A.

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.