Der AVR-/ARDUINO-Faden

Der chaotische Hauptfaden

Moderatoren: Heaterman, Finger, Sven, TDI, Marsupilami72, duese

Name vergessen
Beiträge: 3261
Registriert: Mo 12. Aug 2013, 19:47

Re: Der AVR-/ARDUINO-Faden

Beitrag von Name vergessen »

Hatte das glaub ich schonmal in einem anderen Fred gepostet, aber egal: [url="sbprojects.com/sbbus]der Typ[/url] macht das mit RS232 und Optokopplern. Kann allerdings nur Single Master.
Benutzeravatar
Trax
Beiträge: 1677
Registriert: Mi 30. Okt 2013, 23:21

Re: Der AVR-/ARDUINO-Faden

Beitrag von Trax »

Kann man den ARef pin eines AVR irgendwie als weiteren ADC Chanel missbrauchen?

Datenblat sagt:
ATmega1284P features an internal bandgap refer
ence. This reference is used for Brown-out
Detection, and it can be used as an input to the Analog Comparator or the ADC
Da müsste ich doch wen dich die interne referenz messe und und an der externen unterschiedliche Spannungen anlege unterschiedliches messen können, oder?
Benutzeravatar
MadEngineer
Beiträge: 109
Registriert: Fr 26. Jun 2015, 12:19

Re: Der AVR-/ARDUINO-Faden

Beitrag von MadEngineer »

Ja das müsste gehen. Diesen Klimmzug musste ich mal bei einem STM32 machen. Als Referenzspannung war nur die Versorgungsspannung möglich. Dann die interne Bandgap messen und schon kann man auf Vref, sprich die Versorungungsspannung zurückrechnen. Du weißt ja, dass deine Referenzspannung der Vollausschlag des ADC ist und deine Bandgap-Spannung ist ja auch bekannt..

Bei den AVR müsstest du dann im ADMUX Register:
-REFS1 und REFS0 auf 0 setzen --> externe Referenzpannung via AREF
-MUX4..0 auf 0x1E setzen --> 1,1V Bandgap

Dabei gilt es eigentlich nur zu beachten, dass AVCC immer um +/-0,3V Vcc ist und die AREF irgendwo 1V und AVCC liegt. Der AVCC sollte ja eh über eine Induktivität mit eigenem Entkoppelkondensator an Vcc liegen.
Durch die Auswahl von AVCC als Referenz lässt sich dann auch die Betriebspannung messen. Ist sehr praktisch beim Batteriebetrieb, da es den den Spannungsteiler spart :mrgreen:
Benutzeravatar
Chaoskreator
Beiträge: 943
Registriert: Mo 12. Aug 2013, 20:58
Wohnort: 92xxx

Re: Der AVR-/ARDUINO-Faden

Beitrag von Chaoskreator »

Hallo zusammen,

ich erstelle momentan ein Programm für einen ATTiny85 mit dem avr-gcc 4.8.2 unter Xubuntu 14.04.
ich habe das Problem, dass das DDRB-Register um's Verrecken nicht gesetzt wird. DDRB ist 0, sowohl vor als auch nach dem Ausführen der Funktion.
Ich dachte, solche Anfänger-Probleme hätte ich längst hinter mir. :roll:
Ich habe zum Ausprobieren mal auf 0xFF gesetzt, um das im Disasembly besser erkennen zu können.
Das DDRB-Register hat Adresse 0x17.
Mit Assembler kenne ich mich nicht so gut aus. Wo genau wird da das Register an Adresse 0x17 beschrieben? In der ganzen .lss-Datei finde ich kein "0x17".

Der richtige Controller ist in den Compiler-Flags eingestellt.
#include <avr/io.h> wird inkludiert, sonst würde er ja nicht wissen, was "DDRB" bedeuten soll.
Kompilieren erfolgt ohne Fehler und ohne Warnungen.

Folgender Code

Code: Alles auswählen

inline static void HW_InitIoPins(void)
{
   DDRB =   0xFF;
}
ergibt im Disasembly (die .lss-Datei):

Code: Alles auswählen

inline static void HW_InitIoPins(void)
{
     41c:	cf 93       	push	r28
     41e:	df 93       	push	r29
     420:	cd b7       	in	r28, 0x3d	; 61
     422:	de b7       	in	r29, 0x3e	; 62
   DDRB =   0xFF;
     424:	87 e3       	ldi	r24, 0x37	; 55
     426:	90 e0       	ldi	r25, 0x00	; 0
     428:	2f ef       	ldi	r18, 0xFF	; 255
     42a:	fc 01       	movw	r30, r24
     42c:	20 83       	st	Z, r18
}
     42e:	df 91       	pop	r29
     430:	cf 91       	pop	r28
     432:	08 95       	ret
Matt
Beiträge: 6084
Registriert: So 24. Aug 2014, 21:22

Re: Der AVR-/ARDUINO-Faden

Beitrag von Matt »

ob man lieber nach

Code: Alles auswählen

int main  (void)
{
   DDRB =   0xFF;
}
folgen sollten.. "int main" statt anders..
Ichw eiss nichtmal , wie deine ganze Code aussieht.

Achtung, bin noch eher "leiche" /Anfänger und bastelte mit Arduino Nano, wo ich deren Bootloader abgeschossen habe und INSTA LEDlux RGB plane über Fädeldraht an PWM Output (OCxx) gehängt.. es tut sowie ich erwartet habe.
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Der AVR-/ARDUINO-Faden

Beitrag von Fritzler »

Ich hab meine Antwort mal in dne Code gepackt:

Code: Alles auswählen

424:   87 e3          ldi   r24, 0x37   ; 55		<- 0x37 in RegisterPAAR Laden (lowbyte)
426:   90 e0          ldi   r25, 0x00   ; 0			<- 0x0 in RegisterPAAR Laden (highbyte)
428:   2f ef          ldi   r18, 0xFF   ; 255		<- deine 255 in ein Register packen
42a:   fc 01          movw   r30, r24				<- Registerpaare kopieren (r24 nach r30 und r25 nach r31)
42c:   20 83          st   Z, r18					<- Z Pointerregister ist r31/r30 und die 255 dort hinschreiben
Er schreibt also deine 255 nach 0x37.
Sicher, dasse den tiny85 im makefile angegeben hast und nicht irgendeinen anderen avr?

edit:
upps, hab den Offset vergessen.
Die IOs werden ab Speicheradresse 0x20 eingeblendet.
Also 0x17 + 0x20 = 0x37.
Er schreibt also in DDRB.

Daher ist jetzt die Frage was erwartest du?
Dass jetzt der Pin auf 1 geht?
Dann musste noch PORTB = 255 schreiben.
Benutzeravatar
Chaoskreator
Beiträge: 943
Registriert: Mo 12. Aug 2013, 20:58
Wohnort: 92xxx

Re: Der AVR-/ARDUINO-Faden

Beitrag von Chaoskreator »

Ich erzähle mal die ganze Geschichte.
Ursprünglich hatte ich als Initialisierungscode:

Code: Alles auswählen

inline static void HW_InitIoPins(void)
{
   DDRB =   (1<<PB4) | (1<<PB1);
   PORTB =  (1<<PB2); //Pull-Up
}
Wider Erwarten ließ sich aber mit

Code: Alles auswählen

PORTB |= (1<<PB4);
der Pin PB4 nicht auf HIGH setzen. Er bleibt ständig auf 0 V.

Dann hatte ich im Debugger

Code: Alles auswählen

*(volatile uint8_t *)(0x17)
eingetragen, um die Einstellung im DDRB-Register zu kontrollieren, aber ständig 0 gelesen. Wenn es da ein Offset von 0x20 gibt, erklärt das natürlich warum das so ist.
Ich nutze Code::Blocks als Entwicklungsumgebung. Als Debugger die Kombination gdb und avarice.
Ich habe zwar die Schaltung schon mal kontrolliert. PB4 geht, wie geplant, über 22k auf die Basis eines BC547.
Vielleicht sollte ich das doch nochmal kontrollieren. Nicht dass ich da nicht doch einen Kurzschluss gebaut habe (Lochrasterplatine).
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Der AVR-/ARDUINO-Faden

Beitrag von Fritzler »

Guck mal da: http://www.engbedded.com/fusecalc/ dann tiny85 auswählen
Ausversehen die Clock Output Fuse gesetzt?
Das kommt nämlich an PORTB4 raus und im MHz Bereich misst dein Messgerät garantiert Mist.
Benutzeravatar
Chaoskreator
Beiträge: 943
Registriert: Mo 12. Aug 2013, 20:58
Wohnort: 92xxx

Re: Der AVR-/ARDUINO-Faden

Beitrag von Chaoskreator »

GELÖST!!!!!!!11111einseinseins

Ich hatte das Tiny85-Projekt von einem früheren Projekt kopiert und angepasst. In dem damaligen Projekt nutzte ich eine PWM.
PWM... Na, klingelt's schon? :D

Ein paar Zeilen nach dem Aufruf der Pin-Initialisierungsfunktion wurde folgendes ausgeführt:

Code: Alles auswählen

inline static void HW_InitTimer1ForPwm(void)
{
   TCCR1 = (1<<CS11) | (1<<CS10); //Prescaler PCK/2
   GTCCR =   (1<<PWM1B)   //Pulse Width Modulator B Enable
           | (1<<COM1B1); //Clear the OC1B output line.
}
Natürlich setzt die PWM-Ausgabe den Portpin auf null, weil das OCR-Register null ist.

Falls einer von den µC-Anfängern das liest:
Der Grund für das Problem war, dass ich eine PWM-Ausgabe für den Portpin initialisiert hatte, was ich aber eigentlich nicht wollte!

Die meisten Computer-Probleme sitzen halt doch vor der Tastatur.
*Hirn-->Tisch*

Ich dachte inzwischen schon an einen kaputten Controller. Dieses Wunschdenken, dass es sich um einen Hardware-Defekt handelt, hatte sich aber bei mir noch nie erfüllt. ;)
Matt
Beiträge: 6084
Registriert: So 24. Aug 2014, 21:22

Re: Der AVR-/ARDUINO-Faden

Beitrag von Matt »

klassische Copy&Paste-Fehler..

ist mir auch mal passiert.

Achja, ich erzähle mal eigene blöde Fehler mit AVR..
Ich wollte PWM, OCR1A und OCR1B mit unterschiedliche Werte ansteuern, aber es funktioniert nicht wirklich, als ob OCR1B auf OCR1A einfluss hat. Ich hab daran halbe Stunden rumprobiert...und Registerfunktion verstehen wollen.

Am Ende ist Fehler gefunden, ich habe rote und grüne LED an OC1A/B gehängt, wobei beide LED gemeinsame Widerstand hat (was auch warum bin ich da faul) und LED mit geringere UF leuchtet , also grüne erlischt wieder bzw. dunkelt ab, wenn rote heller aufgesteuert wird..
TDI
Beiträge: 2608
Registriert: Fr 28. Jun 2013, 09:43
Wohnort: plattdeutsches Nordland

Re: Der AVR-/ARDUINO-Faden

Beitrag von TDI »

Moin,

dies ist der Code für einen Arduino, der eine Morsebake steuert. Funktioniert so weit.

Code: Alles auswählen

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(6, 9, 5, 2, 3, 4);

//Define the LED Pin
#define PIN_OUT        13
//Define unit length in ms
#define UNIT_LENGTH    100

//Build a struct with the morse code mapping
static const struct {const char letter, *code;} MorseMap[] =
{
  { 'A', ".-" },
  { 'B', "-..." },
  { 'C', "-.-." },
  { 'D', "-.." },
  { 'E', "." },
  { 'F', "..-." },
  { 'G', "--." },
  { 'H', "...." },
  { 'I', ".." },
  { 'J', ".---" },
  { 'K', ".-.-" },
  { 'L', ".-.." },
  { 'M', "--" },
  { 'N', "-." },
  { 'O', "---" },
  { 'P', ".--." },
  { 'Q', "--.-" },
  { 'R', ".-." },
  { 'S', "..." },
  { 'T', "-" },
  { 'U', "..-" },
  { 'V', "...-" },
  { 'W', ".--" },
  { 'X', "-..-" },
  { 'Y', "-.--" },
  { 'Z', "--.." },
  { ' ', "     " }, //Gap between word, seven units 
    
  { '1', ".----" },
  { '2', "..---" },
  { '3', "...--" },
  { '4', "....-" },
  { '5', "....." },
  { '6', "-...." },
  { '7', "--..." },
  { '8', "---.." },
  { '9', "----." },
  { '0', "-----" },

  { '/', "–..-." },  
  { '.', ".–.–.–" },
  { ',', "--..--" },
  { '?', "..--.." },
  { '!', "-.-.--" },
  { ':', "---..." },
  { ';', "-.-.-." },
  { '(', "-.--." },
  { ')', "-.--.-" },
  { '"', ".-..-." },
  { '@', ".--.-." },
  { '&', ".-..." },
};

void setup()
{
  pinMode( PIN_OUT, OUTPUT );
  digitalWrite( PIN_OUT, LOW );
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
}

void loop()
{
  // set the cursor to (16,1):
  lcd.setCursor(16, 1);
  // set the display to automatically scroll:
  lcd.autoscroll();
  
  
  
  String morseWord = encode( "MORSEBAKE TEST " );
    
  for(int i=0; i<=morseWord.length(); i++)
  {
    
    switch( morseWord[i] )
    {
      case '.': //dit
        digitalWrite( PIN_OUT, HIGH );
       // tone(8,2500);
        delay( UNIT_LENGTH );
       // noTone(8);
        digitalWrite( PIN_OUT, LOW );
        delay( UNIT_LENGTH );
        break;

      case '-': //dah
        digitalWrite( PIN_OUT, HIGH );
       // tone(8,2500);
        delay( UNIT_LENGTH*3 );
        digitalWrite( PIN_OUT, LOW );
       // noTone(8);
        delay( UNIT_LENGTH );  
        break;

      case ' ': //gap
        delay( UNIT_LENGTH );
    }
    
  }
}

String encode(const char *string)
{
  size_t i, j;
  String morseWord = "";
  
  for( i = 0; string[i]; ++i )
  {
    for( j = 0; j < sizeof MorseMap / sizeof *MorseMap; ++j )
    {
      if( toupper(string[i]) == MorseMap[j].letter )
      {
        morseWord += MorseMap[j].code;
        break;
      }
    }
    morseWord += " "; //Add tailing space to seperate the chars
  }

  return morseWord; 
  
   
}

String decode(String morse)
{
  String msg = "";
  
  int lastPos = 0;
  int pos = morse.indexOf(' ');
  while( lastPos <= morse.lastIndexOf(' ') )
  {    
    for( int i = 0; i < sizeof MorseMap / sizeof *MorseMap; ++i )
    {
      if( morse.substring(lastPos, pos) == MorseMap[i].code )
      {
        msg += MorseMap[i].letter;
               }
    }

    lastPos = pos+1;
    pos = morse.indexOf(' ', lastPos);
    
    // Handle white-spaces between words (7 spaces)
    while( morse[lastPos] == ' ' && morse[pos+1] == ' ' )
    {
      pos ++;
    }
  }
 // turn off automatic scrolling
  lcd.noAutoscroll();

  // clear screen for the next loop:
  // lcd.clear();
  return msg;
}
Jetzt möchte ich den Text zeitgleich auch auf einem LCD-Display ausgeben und zwar so, dass man auf dem Display sieht, welches Zeichen gerade als Morsecode ausgegeben wird. Meine Idee ist, dass in der oberen Zeile ein fester Text steht und in der zweiten Zeile der Text von rechts nach links durchgescrollt wird und in der Mitte des Displays (vielleicht reverse oder im Morsetakt blinkend) das gerade gemorste Zeichen zu sehen ist.

Leider bin ich prog-technisch noch zu grün hinter den Ohren um im Code erkennen zu können, an welcher Stelle ich wie den Buchstaben abgreife, der gerade in Morsecode ausgegeben wird.

Danke für Tips und Hilfe

TDI
Benutzeravatar
Raider
Beiträge: 1121
Registriert: Fr 11. Jul 2014, 16:58
Wohnort: Ellerhoop

Re: Der AVR-/ARDUINO-Faden

Beitrag von Raider »

TDI hat geschrieben:
Leider bin ich prog-technisch noch zu grün hinter den Ohren um im Code erkennen zu können, an welcher Stelle ich wie den Buchstaben abgreife, der gerade in Morsecode ausgegeben wird.

TDI
Das wird relativ schwierig, da du erst den Text in Morsecode umwandelst und dann mit der for schleife ausgibst. Man müsste das so umbauen, dass mit encode immer nur der aktuelle Buchstabe in einer for-Schleife umgewandelt wird. Habe das mal grob skizziert, hoffentlich einigermaßen verständlich. Word ist dein eingabetext. Ob der Code jetzt genauso funktioniert, keine Ahnung :D

Code: Alles auswählen


for(int i=0; i<=word.length(); i++ )
{ 
 String morseCharacter = encode(word[i])
 for(int j=0; j<=morseCharacter.length(); j++ )
  { 
    switch( morseCharacter[j] )
    {
      case '.': //dit
        digitalWrite( PIN_OUT, HIGH );
       // tone(8,2500);
        delay( UNIT_LENGTH );
       // noTone(8);
        digitalWrite( PIN_OUT, LOW );
        delay( UNIT_LENGTH );
        break;

      case '-': //dah
        digitalWrite( PIN_OUT, HIGH );
       // tone(8,2500);
        delay( UNIT_LENGTH*3 );
        digitalWrite( PIN_OUT, LOW );
       // noTone(8);
        delay( UNIT_LENGTH );  
        break;

      case ' ': //gap
        delay( UNIT_LENGTH );
    }
}
  
Name vergessen
Beiträge: 3261
Registriert: Mo 12. Aug 2013, 19:47

Re: Der AVR-/ARDUINO-Faden

Beitrag von Name vergessen »

Also bei dem Konstrukt mit dem struct und der linearen Suche rollen sich mir die Fußnägel hoch. ;) Zumindest beim Kodieren wäre ein simpler LUT erheblich effizienter und rückwärts zumindest nicht schlechter. Wenn jetzt auf dem AVR die STL verfügbar ist (was ich nicht weiß), wäre das ein Fall für eine map (Hash-table).

Egal, zur eigentlichen Frage: es wäre gar kein Problem, das zu morsende Wort unkodiert zu speichern, erst vor der Sendeschleife encode() aufzurufen und dann den ohnehin mitlaufenden Zeichenzähler als Index in das unkodierte Wort zu nutzen.
Edit: sorry, geht doch nicht so einfach, weil die Zeichen nicht gleich lang sind, man muß also tatsächlich zeichenweise codieren oder jedes Zeichen einzeln als String oder mit Länge ablegen. /Edit
Profipruckel
Beiträge: 1506
Registriert: Di 13. Aug 2013, 19:10
Wohnort: Niedersachsen Süd-Ost

Re: Der AVR-/ARDUINO-Faden

Beitrag von Profipruckel »

Die meisten Arduinos haben einen AT328 mit 5Volt. Für die Analogeingänge sehe ich im Datenblatt "Leckstrom max. 50 nA @ 2,5 Volt" und irgendwas von 100 MegOhm. Anderweitig wird geschrieben, man solle diese mit Quellwiderständen nicht über 10 kOhm betreiben.

Ja was denn nun, wo im Datenblatt finde ich das? Wie hochohmig darf ich den Spannungsteiler auslegen, um einen 12V-Blei zu messen?
Benutzeravatar
xoexlepox
Beiträge: 4814
Registriert: So 11. Aug 2013, 19:28
Wohnort: So etwa in der Mitte

Re: Der AVR-/ARDUINO-Faden

Beitrag von xoexlepox »

Profipruckel hat geschrieben:Anderweitig wird geschrieben, man solle diese mit Quellwiderständen nicht über 10 kOhm betreiben.
Könnte das an dem "Sample and Hold" liegen, was auf einem Kondensator beruht, der an der zu messenden Spannung anliegt, und bei der Messung davon abgeklemmt wird, um während der Digitalisierung einen stabilen Wert zu haben? Wenn dann noch ein Analogmuliplexer vorgeschaltet ist, um ggf. an mehreren Eingänge zu messen, ist es notwendig, diesen Kondensator auf die entsprechende Spannung aufzuladen, bevor die Messung beginnt. Die Auf/Entladung des Kondensators dauert aufgrund des Quellwiderstands natürlich ein wenig... -> Wenn du nur eine (sich sehr langsam ändernde) Spannung messen willst, ist der hochohmige Wert ok, aber wenn du möchtest, daß ein paar µs nach der Umschaltung des Eingangs die korrekte Spannung ansteht, brauchst du natürlich "etwas mehr Dampf" aus der Quelle ;)

Edith meint: Die genaue Beschreibung (und entsprechende Formeln zur Berechnung der "Wartezeit") solltest du im Bereich "A/D-Wandler" in Datenblatt des Chips finden. Zumindest bei den PICs ist das so.
Profipruckel
Beiträge: 1506
Registriert: Di 13. Aug 2013, 19:10
Wohnort: Niedersachsen Süd-Ost

Re: Der AVR-/ARDUINO-Faden

Beitrag von Profipruckel »

xoexlepox hat geschrieben:
Profipruckel hat geschrieben:Anderweitig wird geschrieben, man solle diese mit Quellwiderständen nicht über 10 kOhm betreiben.
Könnte das an dem "Sample and Hold" liegen, was auf einem Kondensator beruht, ..
Danke für Deine (einzige) Antwort - ich habe das im Datenblatt gefunden, auf Seite 244 von 650:

"When the channel is selected, the source must drive the S/H capacitor through the series resistance (combined resistance in the input path).
The ADC is optimized for analog signals with an output impedance of approximately 10 k? or less. If such a source is used, the sampling time will be negligible. If a source with higher impedance is used, the sampling time will depend on how long time the source needs to charge the S/H capacitor, with can vary widely. The user is recommended to only use low impedance sources with slowly varying signals, since this minimizes the required charge transfer to the S/H capacitor."


Im zugehörigen Prinzipschaltbild sehe ich 14 pF.
Wenn du nur eine (sich sehr langsam ändernde) Spannung messen willst, ist der hochohmige Wert ok, aber wenn du möchtest, daß ein paar µs nach der Umschaltung des Eingangs die korrekte Spannung ansteht,
Ich weiß nicht, wie sich die Arduino-Umgebung da verhält bzw. was hinter "analogRead" stattfindet. Einen Zugriff auf die Wandlungszeit oder das Ready-Bit sehe ich dort nicht.

An anderer Stelle habe ich etwas gefunden, was mir schlüssig scheint: Bei hochohmigem Teiler einen Kondensator drauf, damit der AVR zügig messen kann.

Ich hatte es nicht geschrieben: Ich will alle x Minuten die Spannung eines Akkus messen, ohne deutlich zu dessen Entladung beizutragen, habe also Zeit.
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Der AVR-/ARDUINO-Faden

Beitrag von Fritzler »

Da hilft aber nicht hochohmig, sondern den Spannungsteiler über nen PFET abklemmen wenn der nicht gebraucht wird.

Zu dem Arduino analogread Mumpitz sag ich jetz mal nix... (natürlich haben die daran nicht gedacht)
Benutzeravatar
BMS
Beiträge: 220
Registriert: Di 13. Aug 2013, 10:56

Re: Der AVR-/ARDUINO-Faden

Beitrag von BMS »

Oder hochohmig + Kondensator vom ADC Eingang nach GND. Oder CD4066 als Analogschalter.
Vor kurzem im Roboternetz
(bin dort auch als BMS unterwegs)
Grüße, Bernhard
Benutzeravatar
xoexlepox
Beiträge: 4814
Registriert: So 11. Aug 2013, 19:28
Wohnort: So etwa in der Mitte

Re: Der AVR-/ARDUINO-Faden

Beitrag von xoexlepox »

Profipruckel hat geschrieben:Einen Zugriff auf die Wandlungszeit oder das Ready-Bit sehe ich dort nicht.
Hmmm, ich habe mich bisher nur recht oberflächlich mit den ATMELs beschäftigt (und die Arduino-Libs sofort "abgeklemmt") , gehe aber mal davon aus, daß du die Funtion des "AnalogRead" auch "zu Fuß" (mit Zugriffen auf die Registerbits) realisieren kannst. Beim PIC gibt es nur ein Bit, welches beim Start der A/D-Wandlung gesetzt wird, und beim Ende der Wandlung wieder gelöscht wird (und ggf. einen Interrupt auslöst). Wie lange es dauert, den S&H-Kondensator zu laden, "weiss" die Hardware natürlich nicht ;)
Bei hochohmigem Teiler einen Kondensator drauf, damit der AVR zügig messen kann.
Das könnte bei der Umschaltung von A/D-Eingängen nützlich sein, aber der externe Kondensator muss natürlich auch von der hochohmigen Quelle auf die korrekte Spannung gebracht werden ;)
Ich will alle x Minuten die Spannung eines Akkus messen, ohne deutlich zu dessen Entladung beizutragen, habe also Zeit.
Wenn du keine anderen Analogeingänge verwendest, und somit den Analogmultiplexer nicht verwendest, kannst du es m.E. durchaus hochohmig belassen.
Profipruckel
Beiträge: 1506
Registriert: Di 13. Aug 2013, 19:10
Wohnort: Niedersachsen Süd-Ost

Re: Der AVR-/ARDUINO-Faden

Beitrag von Profipruckel »

Fritzler hat geschrieben:Da hilft aber nicht hochohmig, sondern den Spannungsteiler über nen PFET abklemmen wenn der nicht gebraucht wird.
In meinem ursprünglichen Entwurf habe ich das so. Es ist eine Rechenaufgabe: mA nur für die Messung oder µA dauerhaft.
Zu dem Arduino analogread Mumpitz sag ich jetz mal nix... (natürlich haben die daran nicht gedacht)
"Arduino analogread" habe ich nicht wirklich verstanden. In meiner Lötstation werfe ich den ersten Meßwert weg, weil der sporadisch grob falsch ist. Dann hole ich mir zehn weitere im Abstand von je einer ms und rechne den Mittelwert - passt.
Profipruckel
Beiträge: 1506
Registriert: Di 13. Aug 2013, 19:10
Wohnort: Niedersachsen Süd-Ost

Re: Der AVR-/ARDUINO-Faden

Beitrag von Profipruckel »

BMS hat geschrieben:Oder hochohmig + Kondensator vom ADC Eingang nach GND. Oder CD4066 als Analogschalter.
Vor kurzem im Roboternetz
(bin dort auch als BMS unterwegs)
Grüße, Bernhard
Na ja, auch das Roboternetz macht mich nicht erheblich schlauer. Mit Deinem Beitrag 21.07.2016, 16:29 bringst Du den großen Kondensator ins Spiel, eine klare Aussage zum Meßfehler sehe ich aber auch dort nicht.

Ich denke, ich werde einen niederohmigen Teiler verwenden und schalten - für ein Einzelstück kann ich die zusätzlichen Bauteilekosten gerade noch aufbringen.

Ach ja, Edit: Einen 4066 werde ich mir für einen Kanal nicht antun, eher ein PhotoMos-Relay, die habe ich im Dutzend da.
xanakind
Beiträge: 12538
Registriert: So 11. Aug 2013, 21:55

Re: Der AVR-/ARDUINO-Faden

Beitrag von xanakind »

Ich bin gerade dabei mir für´s Auto eine neue Steuerung der Sitzheizung(und andere Dinge...) zu basteln.....
die Originale Sitzheizung kann nur Volle Kanne die Eier grillen oder aus.
Darum kommen andere Schalter mit Potis aus einem Opel rein.

Klappt auch alles wunderbar, hat jedoch einen Haken:

Stehen die Regler auf kleinster Stufe, bekommt die CPU (Arduino Nano) 5 Volt.
auf der höchsten Stufe dann entsprechend nurnoch 1 Volt.

Gibt s eine einfache Möglichkeit den eingelesen Analogen Wert der beiden Potis zu negieren?

Achso: Hier der Hochkomplizierte Programmabschnitt:

Code: Alles auswählen

//Sitzheizung_rechts
  if (digitalRead(sitz_rechts_on)){
  val = analogRead (sitz_rechts_out);
  analogWrite (sitz_rechts, val /4);
  }else{
    digitalWrite(sitz_rechts, LOW);
Vielleicht kann mir da wer weiterhelfen? :)
Benutzeravatar
Bauteiltöter
Beiträge: 254
Registriert: So 11. Aug 2013, 17:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bauteiltöter »

Code: Alles auswählen

val=1034-val;
So zum Beispiel?
Dann gibts bei 0V 1034 als Wert und bei 5V 0.
xanakind
Beiträge: 12538
Registriert: So 11. Aug 2013, 21:55

Re: Der AVR-/ARDUINO-Faden

Beitrag von xanakind »

Vielen lieben Dank!
läuft! :D
jetzt muss ich nurnoch rausfinden, warum auf der letzten Stufe wieder etwas weniger Leistung rauskommt.....
vielleicht machen die Opelschalter intern irgend einen Murks.....mal schauen.
Benutzeravatar
Sven
Beiträge: 4421
Registriert: Fr 28. Jun 2013, 12:52
Wohnort: Sechsundzwanzigdreisechzehn

Re: Der AVR-/ARDUINO-Faden

Beitrag von Sven »

Wie kommst du auf 1034?
Der AD Wandler hat doch 10 Bit, damit sollte 1023 der Maximalwert sein ;)
xanakind
Beiträge: 12538
Registriert: So 11. Aug 2013, 21:55

Re: Der AVR-/ARDUINO-Faden

Beitrag von xanakind »

das würde auch das komische Verhalten auf der letzten Stufe erklären....
Die Hardware ist nämlich ok
Benutzeravatar
Bauteiltöter
Beiträge: 254
Registriert: So 11. Aug 2013, 17:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bauteiltöter »

Ja genau, und beim Maximalwert des ADCs wollte Xana doch den Minimalwert seiner Variable haben, oder habe ich das falsch verstanden?
xanakind
Beiträge: 12538
Registriert: So 11. Aug 2013, 21:55

Re: Der AVR-/ARDUINO-Faden

Beitrag von xanakind »

Ne, du hast das schon richtig verstanden, funktioniert prinzipiell ja auch schon ziemlich gut.
Ich habe das nun gemacht:

Code: Alles auswählen

//Sitzheizung_rechts
  if (digitalRead(sitz_rechts_on)){
  val = analogRead (sitz_rechts_out);
  analogWrite (sitz_rechts, val=1023-val/4+25);
  }else{
    digitalWrite(sitz_rechts, LOW);
Funktioniert wunderbar! :D
Benutzeravatar
Sven
Beiträge: 4421
Registriert: Fr 28. Jun 2013, 12:52
Wohnort: Sechsundzwanzigdreisechzehn

Re: Der AVR-/ARDUINO-Faden

Beitrag von Sven »

Der Maximalwert eines AD Wandlers ist immer (2^Q)-1 wobei Q die Anzahl von Bits ist :)
Benutzeravatar
Bauteiltöter
Beiträge: 254
Registriert: So 11. Aug 2013, 17:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bauteiltöter »

Ja natürlich. Args. Tippfehler und nicht gemerkt. Natürlich meinte ich 1023, nicht 1034.
Benutzeravatar
Wurstblinker
Beiträge: 601
Registriert: Di 13. Sep 2016, 21:09
Wohnort: weit West

Re: Der AVR-/ARDUINO-Faden

Beitrag von Wurstblinker »

Hallo Leute
Ich glaube diesmal habe ich mich übernommen……….

Eine DRO (digital read out) Anzeige für die Drehmaschine,
mit einer optischen Maus als Geber und einer LCD Anzeige via Arduino ist wohl doch ein wenig hoch gegriffen für das erste Mikrocontroller Projekt überhaupt.

C Programmieren ist absolutes Neuland für mich , der seine bisherigen Gehversuche vor 20 Jahren mit Basic begann und vor 19 Jahren wider (bis auf ein paar kurze Ausflüge) beendete.

Aber Hallo Welt schreiben hat mich noch nie interessiert ,also Nase zuhalten und rein ins tiefe Wasser.

Diesmal leider zu tief……….
Seit 3 tagen komm ich keinen schritt mehr weiter…………….

Die Hardware ist kein Problem, und der Krempel aus dem Müll und funktioniert tadellos.

Da ich nicht programmieren kann (bin aber lernwillig ) habe ich mir erst mal alles benötigte im Netz "zusammengeklaut", und es nach ner knappen Woche auch zum Laufen gebracht.

Ist zustand :
Die Funkmaus gibt ihre Positionsänderung an den Arduino und der schreibt sie netterweise auch aufs Display.

Bild

Allerdings nur die Positionsänderungen , ich hätte aber gerne dort einen Positionswert der sich entsprechend der Mausbewegung ändert z.b. x300 und wenn die Maus sich 50 bewegt dann eben x 350
im Moment steht dann x50 oder x -20 weil die Maus sich in x +50 oder -20 bewegt hat.

Hätte nicht gedacht das das so ein großes Problem wird nachdem ich mich durch den Rest
von 0 an, auch durchkämpfen konnte.

Aber mir fehlt im Moment jeglicher Ansatz um das Programm meinen wünschen entsprechend zu ändern.
Hoffe ich habe wenigstens die entscheidenden Stellen durch die 3 gestrichelten Linien richtig identifiziert…. :?

Code: Alles auswählen

/*============================ EG LABS ===================================//
 
 Demonstration on how to use PS2 MOUSE with an arduino board
 
 The circuit:
 LCD:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 7
 * LCD D5 pin to digital pin 6
 * LCD D6 pin to digital pin 5
 * LCD D7 pin to digital pin 4
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD pin 3
 * LED anode attached to digital output 9
 * LED cathode attached to ground through a 1K resistor
 MOUSE:
 DATA PIN TO PIN NUMBER 8
 CLOCK PIN TO PIN NUMBER 3
============================== EG LABS ===================================*/
 
 
#include "PS2Mouse.h"
#define MOUSE_DATA 8                                                              
#define MOUSE_CLOCK 3
// include the library code:
#include <LiquidCrystal.h>
 
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
 
PS2Mouse mouse(MOUSE_CLOCK, MOUSE_DATA, STREAM);                              // initializing the PS2 library
 
int data[2];
int led = 9;

void setup()
{
  pinMode(led, OUTPUT);     
  lcd.begin(16, 2);
  lcd.print("ENGINEERS GARAGE");
  lcd.setCursor(0, 1);
  lcd.print("    PS2 MOUSE   ");
  delay(2000);
  lcd.clear();
  Serial.begin(38400);
  
  mouse.initialize();                                                   // initializing the PS2 mouse connected with the Arduino
  digitalWrite(led, HIGH);  
}
 
void loop()
//--------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------Hier meine bescheidenen und sinnlose Versuche----------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
{
  mouse.report(data);                                                       // get data from the mouse
int wertx; //zusätzliche variable für data1 definiert
int werty; //zusätzliche variable für data2 definiert

  if((data[1] != 0) || (data[2] != 0) || (data[0] != 8))
   
  {
  
      lcd.clear();
      Serial.print("X = "); //ab 38000baud darstellung richtig
      lcd.print("X=");
      Serial.print( data[1]);                                                 // X Movement Data
      lcd.print( wertx + data[1]); //einfach + wertx geht nicht ??
      lcd.setCursor(0, 1);
      
      Serial.print(", Y = ");
      lcd.print("Y=");
      Serial.print(data[2]);                                                 // Y Movement Data
      lcd.print(data[2]);  
      
      if(data[0] == 9)
            Serial.print(", LEFT BUTTON");                                  // Status Byte
      else if (data[0] == 10)
            Serial.print(", RIGHT BUTTON");                                 // Status Byte
      else if (data[0] == 12)
            Serial.print(", CENTRE BUTTON");                                // Status Byte
      else;
      
      Serial.println();
  }else;
  wertx = data[1] ;  //neue variable für data, aber wie baue ich die hier um damit die "neue data"
  werty = data[2] ; //dazugezählt oder abgezogen wird ?
      
}
//--------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
//******** PS2.h*******//
//#include "WConstants.h"
#include "HardwareSerial.h"
#include "PS2Mouse.h"
#include "Arduino.h"
 
PS2Mouse::PS2Mouse(int clock_pin, int data_pin, int mode) {
  _clock_pin = clock_pin;
  _data_pin = data_pin;
  _mode = mode;
  _initialized = false;  
  _disabled = true;
  _enabled = false;
}
 
int PS2Mouse::clock_pin() {
  return _clock_pin;
}
 
int PS2Mouse::data_pin() {
  return _data_pin;
}
 
void PS2Mouse::initialize() {
  pull_high(_clock_pin);
  pull_high(_data_pin);
  delay(20);
  write(0xff); // Send Reset to the mouse
  read_byte();  // Read ack byte 
  delay(20); // Not sure why this needs the delay
  read_byte();  // blank 
  read_byte();  // blank
  delay(20); // Not sure why this needs the delay
  if (_mode == REMOTE) {
    set_remote_mode();
  } else {
    enable_data_reporting(); // Tell the mouse to start sending data again
  }
  delayMicroseconds(100);
  _initialized = 1;
}
 
void PS2Mouse::set_mode(int data) {
  if (_mode == STREAM) {
    disable_data_reporting(); // Tell the mouse to stop sending data.
  }
  write(data);  // Send Set Mode
  read_byte();  // Read Ack byte
  if (_mode == STREAM) {
    enable_data_reporting(); // Tell the mouse to start sending data again
  }
  if (_initialized) {
    delayMicroseconds(100);    
  }
}
 
void PS2Mouse::set_remote_mode() {
  set_mode(0xf0);
  _mode = REMOTE;
}
  
void PS2Mouse::set_stream_mode() {
  set_mode(0xea);
  _mode = STREAM;
}
 
void PS2Mouse::set_sample_rate(int rate) {
  if (_mode == STREAM) {
    disable_data_reporting(); // Tell the mouse to stop sending data.
  }
  write(0xf3); // Tell the mouse we are going to set the sample rate.
  read_byte(); // Read Ack Byte
  write(rate); // Send Set Sample Rate
  read_byte(); // Read ack byte
  if (_mode == STREAM) {
    enable_data_reporting(); // Tell the mouse to start sending data again
  }
  delayMicroseconds(100);
}
 
void PS2Mouse::set_scaling_2_1() {
  set_mode(0xe7); // Set the scaling to 2:1
}
 
void PS2Mouse::set_scaling_1_1() {
  set_mode(0xe6); // set the scaling to 1:1
}
 
// This only effects data reporting in Stream mode.
void PS2Mouse::enable_data_reporting() {
  if (!_enabled) {
    write(0xf4); // Send enable data reporting
    read_byte(); // Read Ack Byte
    _enabled = true;
  }
}
 
// Disabling data reporting in Stream Mode will make it behave like Remote Mode
void PS2Mouse::disable_data_reporting() {
  if (!_disabled) {
    write(0xf5); // Send disable data reporting
    read_byte(); // Read Ack Byte    
    _disabled = true;
  }
}
 
void PS2Mouse::set_resolution(int resolution) {
  if (_mode == STREAM) {
    enable_data_reporting();
  }
  write(0xe8); // Send Set Resolution
  read_byte(); // Read ack Byte
  write(resolution); // Send resolution setting
  read_byte(); // Read ack Byte
  if (_mode == STREAM) {
    disable_data_reporting();
  }
  delayMicroseconds(100);
}
 
void PS2Mouse::write(int data) {
  char i;
  char parity = 1;
  pull_high(_data_pin);
  pull_high(_clock_pin);
  delayMicroseconds(300);
  pull_low(_clock_pin);
  delayMicroseconds(300);
  pull_low(_data_pin);
  delayMicroseconds(10);
  pull_high(_clock_pin); // Start Bit
  while (digitalRead(_clock_pin)) {;} // wait for mouse to take control of clock)
  // clock is low, and we are clear to send data 
  for (i=0; i < 8; i++) {
    if (data & 0x01) {
      pull_high(_data_pin);
    } else {
      pull_low(_data_pin);
    }
    // wait for clock cycle 
    while (!digitalRead(_clock_pin)) {;}
    while (digitalRead(_clock_pin)) {;}
    parity = parity ^ (data & 0x01);
    data = data >> 1;
  }  
  // parity 
  if (parity) {
    pull_high(_data_pin);
  } else {
    pull_low(_data_pin);
  }
  while (!digitalRead(_clock_pin)) {;}
  while (digitalRead(_clock_pin)) {;}  
  pull_high(_data_pin);
  delayMicroseconds(50);
  while (digitalRead(_clock_pin)) {;}
  while ((!digitalRead(_clock_pin)) || (!digitalRead(_data_pin))) {;} // wait for mouse to switch modes
  pull_low(_clock_pin); // put a hold on the incoming data.
}
 
//--------------------------------------------------------------------------------------------------------------------------------
//------------------------------Von hier kommt wohl data1 und 2 ?  --------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
int * PS2Mouse::report(int data[]) {
  write(0xeb); // Send Read Data
  read_byte(); // Read Ack Byte
  data[0] = read(); // Status bit
  data[1] = read_movement_x(data[0]); // X Movement Packet
  data[2] = read_movement_y(data[0]); // Y Movement Packet
   return data;
}
//--------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
int PS2Mouse::read() {
  return read_byte();
}
 
int PS2Mouse::read_byte() {
  int data = 0;
  pull_high(_clock_pin);
  pull_high(_data_pin);
  delayMicroseconds(50);
  while (digitalRead(_clock_pin)) {;}
  delayMicroseconds(5);  // not sure why.
  while (!digitalRead(_clock_pin)) {;} // eat start bit
  for (int i = 0; i < 8; i++) {
    bitWrite(data, i, read_bit());
  }
  read_bit(); // Partiy Bit 
  read_bit(); // Stop bit should be 1
  pull_low(_clock_pin);
  return data;
}
 
int PS2Mouse::read_bit() {
  while (digitalRead(_clock_pin)) {;}
  int bit = digitalRead(_data_pin);  
  while (!digitalRead(_clock_pin)) {;}
  return bit;
}
 
int PS2Mouse::read_movement_x(int status) {
  int x = read();
  if (bitRead(status, 4)) {
    for(int i = 8; i < 16; ++i) {
      x |= (1<<i);
    }
  }
  return x;
}
 
int PS2Mouse::read_movement_y(int status) {
  int y = read();
  if (bitRead(status, 5)) {
    for(int i = 8; i < 16; ++i) {
      y |= (1<<i);
    }
  }
  return y;
}
 
void PS2Mouse::pull_low(int pin) {
 pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);  
}
 
void PS2Mouse::pull_high(int pin) {
  pinMode(pin, INPUT);
  digitalWrite(pin, HIGH);
}
und zum 2. noch die PS2Mouse.h

Code: Alles auswählen

#ifndef PS2Mouse_h
 
#define PS2Mouse_h
#define REMOTE 1
#define STREAM 2
 
class PS2Mouse
{
  private:
    int _clock_pin;
    int _data_pin;
    int _mode;
    int _initialized;
    int _enabled;
    int _disabled;
    int read_byte();
    int read_bit();
    int read_movement_x(int);
    int read_movement_y(int);
    void pull_high(int);
    void pull_low(int);
    void set_mode(int);
  public:
    PS2Mouse(int, int, int mode = REMOTE);
    void initialize();
    int clock_pin();
    int data_pin();
    int read();
    int* report(int data[]);
    void write(int);
    void enable_data_reporting();
    void disable_data_reporting();
    void set_remote_mode();
    void set_stream_mode();
    void set_resolution(int);
    void set_scaling_2_1();
    void set_scaling_1_1();
    void set_sample_rate(int);
};
 
#endif

// http://www.engineersgarage.com/embedded/arduino/how-to-interface-ps2-mouse-with-arduino


//Da ich weiß welche Arbeit hinter dem bisherigen code steckt, gibt’s hier auch die Quelle.
Hoffe jemand hat nen Rettungsring, damit ich nicht komplett absaufe

bye, Andi
Blueloop
Beiträge: 148
Registriert: Mo 12. Aug 2013, 17:59
Wohnort: Ettlingen

Re: Der AVR-/ARDUINO-Faden

Beitrag von Blueloop »

Hallo,


die beiden Zeilen:

int wertx; //zusätzliche variable für data1 definiert
int werty; //zusätzliche variable für data2 definiert

ausserhalb der loop Funktion verschieben, damit sie nicht bei jedem loop Durchlauf gelöscht werden und dann anstatt:

wertx = data[1] ; //neue variable für data, aber wie baue ich die hier um damit die "neue data"
werty = data[2] ; //dazugezählt oder abgezogen wird ?

wertx = wertx + data[1];
werty = werty + data[2];

oder kürzer (generiert den selben code, nur andere schreibweise):

wertx += data[1];
werty += data[2];
Benutzeravatar
Wurstblinker
Beiträge: 601
Registriert: Di 13. Sep 2016, 21:09
Wohnort: weit West

Re: Der AVR-/ARDUINO-Faden

Beitrag von Wurstblinker »

Hallo,
vielen Dank das war schon mal das halbe Problem…

Int wertx und y aus der Loop raus zu nehmen war der entscheidende Tipp. mny tnx @ Blueloop

Die Anzeige funktioniert jetzt,

aber leider nur in y (data[2])

Das hängt wohl damit zusammen das data[2] schon gleich zu anfang ( Zeile 35)
deklariert ist.

Ein zusätzliches int data[1]; an dieser Stelle ergibt leider die Fehlermeldung:
36: error: conflicting declaration 'int data [1]'
35: error: 'data' has a previous declaration as 'int data [2]'

Wie komme ich denn an den wert von data [1]ran ?

B.z.w. wie bekomme ich ihn sauber in eine neue variable?

Brauche ihn ja auch später noch um die schritt / mm Umrechnung zu machen.

Die entscheidenden stellen sind (hoffentlich) wieder zwischen den 3 Linien
bye, Andreas

Code: Alles auswählen

/*============================ EG LABS ===================================//
 
 Demonstration on how to use PS2 MOUSE with an arduino board
 
 The circuit:
 LCD:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 7
 * LCD D5 pin to digital pin 6
 * LCD D6 pin to digital pin 5
 * LCD D7 pin to digital pin 4
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD pin 3
 * LED anode attached to digital output 9
 * LED cathode attached to ground through a 1K resistor
 MOUSE:
 DATA PIN TO PIN NUMBER 8
 CLOCK PIN TO PIN NUMBER 3
============================== EG LABS ===================================*/
 
 
#include "PS2Mouse.h"
#define MOUSE_DATA 8                                                              
#define MOUSE_CLOCK 3
// include the library code:
#include <LiquidCrystal.h>
 
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
 
PS2Mouse mouse(MOUSE_CLOCK, MOUSE_DATA, STREAM);                              // initializing the PS2 library
int data[2];
//int data[1];waehre ja auch zu einfach gewesen
int led = 9;
int wertx; //zusätzliche variable für data1 definiert
 int werty; //zusätzliche variable für data2 definiert
void setup()
{
  pinMode(led, OUTPUT);     
  lcd.begin(16, 2);
  lcd.print("ENGINEERS GARAGE");
  lcd.setCursor(0, 1);
  lcd.print("    PS2 MOUSE   ");
  delay(2000);
  lcd.clear();
  Serial.begin(38400);
  
  mouse.initialize();                                                   // initializing the PS2 mouse connected with the Arduino
  digitalWrite(led, HIGH);  
}
 
void loop()
//----------------------------------------------------------------------------------------------------------------------------
//-----------------------------------Hier meine bescheidenen und sinnlose Versuche---------------------------
//----------------------------------------------------------------------------------------------------------------------------
  mouse.report(data);                                                       // get data from the mouse
 
  if((data[1] != 0) || (data[2] != 0) || (data[0] != 8))
   
  {
  
      lcd.clear();
      Serial.print("X = "); //ab 38000baud darstellung richtig
      lcd.print("X=");
      Serial.print( data[1]);                                                 // X Movement Data
      
      lcd.print( wertx); //einfach  wertx geht nicht , gibt immer noch nur
                               // die Unterschiede aber nicht den Gesamtwert aus
     
      lcd.setCursor(0, 1);
      
      Serial.print(", Y = ");
      lcd.print("Y=");
      Serial.print(data[2]);                                                 // Y Movement Data
      lcd.print(werty);     //funktioniert !
      
      if(data[0] == 9)
            Serial.print(", LEFT BUTTON");                                  // Status Byte
      else if (data[0] == 10)
            Serial.print(", RIGHT BUTTON");                                 // Status Byte
      else if (data[0] == 12)
            Serial.print(", CENTRE BUTTON");                                // Status Byte
      else;
      
      Serial.println();
  }else;
  wertx = wertx+data[1] ;  //neue variable für data,
 
 werty = werty+data[2] ; //funktioniert aber leider nur mit data2 und nicht mit data1
                                     //data[1] wird ja weiter unten(markiert) generiert komme 
                                     //ich dort irgendwie an den wert ?
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
//******** PS2.h*******//
//#include "WConstants.h"
#include "HardwareSerial.h"
#include "PS2Mouse.h"
#include "Arduino.h"
 
PS2Mouse::PS2Mouse(int clock_pin, int data_pin, int mode) {
  _clock_pin = clock_pin;
  _data_pin = data_pin;
  _mode = mode;
  _initialized = false;  
  _disabled = true;
  _enabled = false;
}
 
int PS2Mouse::clock_pin() {
  return _clock_pin;
}
 
int PS2Mouse::data_pin() {
  return _data_pin;
}
 
void PS2Mouse::initialize() {
  pull_high(_clock_pin);
  pull_high(_data_pin);
  delay(20);
  write(0xff); // Send Reset to the mouse
  read_byte();  // Read ack byte 
  delay(20); // Not sure why this needs the delay
  read_byte();  // blank 
  read_byte();  // blank
  delay(20); // Not sure why this needs the delay
  if (_mode == REMOTE) {
    set_remote_mode();
  } else {
    enable_data_reporting(); // Tell the mouse to start sending data again
  }
  delayMicroseconds(100);
  _initialized = 1;
}
 
void PS2Mouse::set_mode(int data) {
  if (_mode == STREAM) {
    disable_data_reporting(); // Tell the mouse to stop sending data.
  }
  write(data);  // Send Set Mode
  read_byte();  // Read Ack byte
  if (_mode == STREAM) {
    enable_data_reporting(); // Tell the mouse to start sending data again
  }
  if (_initialized) {
    delayMicroseconds(100);    
  }
}
 
void PS2Mouse::set_remote_mode() {
  set_mode(0xf0);
  _mode = REMOTE;
}
  
void PS2Mouse::set_stream_mode() {
  set_mode(0xea);
  _mode = STREAM;
}
 
void PS2Mouse::set_sample_rate(int rate) {
  if (_mode == STREAM) {
    disable_data_reporting(); // Tell the mouse to stop sending data.
  }
  write(0xf3); // Tell the mouse we are going to set the sample rate.
  read_byte(); // Read Ack Byte
  write(rate); // Send Set Sample Rate
  read_byte(); // Read ack byte
  if (_mode == STREAM) {
    enable_data_reporting(); // Tell the mouse to start sending data again
  }
  delayMicroseconds(100);
}
 
void PS2Mouse::set_scaling_2_1() {
  set_mode(0xe7); // Set the scaling to 2:1
}
 
void PS2Mouse::set_scaling_1_1() {
  set_mode(0xe6); // set the scaling to 1:1
}
 
// This only effects data reporting in Stream mode.
void PS2Mouse::enable_data_reporting() {
  if (!_enabled) {
    write(0xf4); // Send enable data reporting
    read_byte(); // Read Ack Byte
    _enabled = true;
  }
}
 
// Disabling data reporting in Stream Mode will make it behave like Remote Mode
void PS2Mouse::disable_data_reporting() {
  if (!_disabled) {
    write(0xf5); // Send disable data reporting
    read_byte(); // Read Ack Byte    
    _disabled = true;
  }
}
 
void PS2Mouse::set_resolution(int resolution) {
  if (_mode == STREAM) {
    enable_data_reporting();
  }
  write(0xe8); // Send Set Resolution
  read_byte(); // Read ack Byte
  write(resolution); // Send resolution setting
  read_byte(); // Read ack Byte
  if (_mode == STREAM) {
    disable_data_reporting();
  }
  delayMicroseconds(100);
}
 
void PS2Mouse::write(int data) {
  char i;
  char parity = 1;
  pull_high(_data_pin);
  pull_high(_clock_pin);
  delayMicroseconds(300);
  pull_low(_clock_pin);
  delayMicroseconds(300);
  pull_low(_data_pin);
  delayMicroseconds(10);
  pull_high(_clock_pin); // Start Bit
  while (digitalRead(_clock_pin)) {;} // wait for mouse to take control of clock)
  // clock is low, and we are clear to send data 
  for (i=0; i < 8; i++) {
    if (data & 0x01) {
      pull_high(_data_pin);
    } else {
      pull_low(_data_pin);
    }
    // wait for clock cycle 
    while (!digitalRead(_clock_pin)) {;}
    while (digitalRead(_clock_pin)) {;}
    parity = parity ^ (data & 0x01);
    data = data >> 1;
  }  
  // parity 
  if (parity) {
    pull_high(_data_pin);
  } else {
    pull_low(_data_pin);
  }
  while (!digitalRead(_clock_pin)) {;}
  while (digitalRead(_clock_pin)) {;}  
  pull_high(_data_pin);
  delayMicroseconds(50);
  while (digitalRead(_clock_pin)) {;}
  while ((!digitalRead(_clock_pin)) || (!digitalRead(_data_pin))) {;} // wait for mouse to switch modes
  pull_low(_clock_pin); // put a hold on the incoming data.
}
 
//--------------------------------------------------------------------------------------------------------------------------------
//------------------------------Von hier kommt wohl data1 und 2 ?  ----------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
int * PS2Mouse::report(int data[]) {
  write(0xeb); // Send Read Data
  read_byte(); // Read Ack Byte
  data[0] = read(); // Status bit
  data[1] = read_movement_x(data[0]); // X Movement Packet
  data[2] = read_movement_y(data[0]); // Y Movement Packet
   return data;
 
}
//--------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------
int PS2Mouse::read() {
  return read_byte();
}
 
int PS2Mouse::read_byte() {
  int data = 0;
  pull_high(_clock_pin);
  pull_high(_data_pin);
  delayMicroseconds(50);
  while (digitalRead(_clock_pin)) {;}
  delayMicroseconds(5);  // not sure why.
  while (!digitalRead(_clock_pin)) {;} // eat start bit
  for (int i = 0; i < 8; i++) {
    bitWrite(data, i, read_bit());
  }
  read_bit(); // Partiy Bit 
  read_bit(); // Stop bit should be 1
  pull_low(_clock_pin);
  return data;
}
 
int PS2Mouse::read_bit() {
  while (digitalRead(_clock_pin)) {;}
  int bit = digitalRead(_data_pin);  
  while (!digitalRead(_clock_pin)) {;}
  return bit;
}
 
int PS2Mouse::read_movement_x(int status) {
  int x = read();
  if (bitRead(status, 4)) {
    for(int i = 8; i < 16; ++i) {
      x |= (1<<i);
    }
  }
  return x;
}
 
int PS2Mouse::read_movement_y(int status) {
  int y = read();
  if (bitRead(status, 5)) {
    for(int i = 8; i < 16; ++i) {
      y |= (1<<i);
    }
  }
  return y;
}
 
void PS2Mouse::pull_low(int pin) {
 pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);  
}
 
void PS2Mouse::pull_high(int pin) {
  pinMode(pin, INPUT);
  digitalWrite(pin, HIGH);
}

Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Der AVR-/ARDUINO-Faden

Beitrag von Fritzler »

Benutzeravatar
Wurstblinker
Beiträge: 601
Registriert: Di 13. Sep 2016, 21:09
Wohnort: weit West

Re: Der AVR-/ARDUINO-Faden

Beitrag von Wurstblinker »

Bitte nicht Falsch verstehen !

Ich weiß das mir die Grundlagen fehlen.
Und das hier stochern im Nebel angesagt ist.

Das Ziel ist aber nicht programmieren zu lernen, sondern eine DRO Anzeige
für die Drehbank zu bauen.
Die ich mir Fertig einfach nicht leisten kann.

Und dazu fehlen mir jetzt noch 2 Schritte:

1. diesen blöden wert von data1 aufs Display zu bekommen
2. das ganze in ein Gehäuse zu packen und an die Drehe zu spaxen.

Deshalb dachte ich, dass ich hier mit meinen 2 Fragen an der richtigen stelle währe.

Habe mich wirklich bemüht das Problem genau zu beschreiben
und auf einen 2. tipp, wie den 1. von blueloop gehofft der das Problem löst.
Ich erwarte ja nicht das jemand das für mich fertig programmiert und bin auch schon über
einen Hinweis froh.

Natürlich wäre es schön den gesamten Programmcode verstehen zu können..
Aber um mich so tief in die Materie einzuarbeiten, fehlt mir leider auch etwas Lebenszeit,
die ich bisher in das Lernen anderer dinge investiert habe,
von denen nun andere Leute bei anderen Fragen profitieren können.

bye, andi
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Der AVR-/ARDUINO-Faden

Beitrag von Fritzler »

Nich rausreden, sondern C lernen.
Ich will doch auch nicht auf den Mond fliegen ohne vorher eine Ausbildung absolviert zu haben.
Anse
Beiträge: 2278
Registriert: Mo 12. Aug 2013, 21:30
Wohnort: Bühl (Baden)

Re: Der AVR-/ARDUINO-Faden

Beitrag von Anse »

Code: Alles auswählen

int data[2];
Wenn Arduino dem C-Standard folgt wird hier ein Array mit zwei Elementen definiert.

In dieser Funktion wird aber auf ein drittes Element geschrieben. Das gibt normalerweise Probleme.

Code: Alles auswählen

int * PS2Mouse::report(int data[]) {
  write(0xeb); // Send Read Data
  read_byte(); // Read Ack Byte
  data[0] = read(); // Status bit
  data[1] = read_movement_x(data[0]); // X Movement Packet
  data[2] = read_movement_y(data[0]); // Y Movement Packet
   return data;
 
}
Also sollte da oben

Code: Alles auswählen

int data[3];
stehen.

Das ist mir als erstes aufgefallen. Kann also noch etwas mehr nicht stimmen.
Benutzeravatar
Harley
Beiträge: 1160
Registriert: So 11. Aug 2013, 21:16
Wohnort: Regensburg

Re: Der AVR-/ARDUINO-Faden

Beitrag von Harley »

Hallo Wurstblinker,
ich glaube, es ist keine gute Idee, eine Maus als DRO zu verwenden.
Siehe die Beiträge im Sensoren-Thread.

An einer Drehe braucht man eine absolut zuverlässige Anzeige auf 1/100 mm genau!
Sonst wird das nichts. Wie willst Du die Maus mit dem Drehbankbett überhaupt zuverlässig koppeln?

Ich hab in der letzten Finger-Postille ein DRO mit billigen China-Schiebelehren und einem Arduino beschrieben.
Billig, gut und absolut zuverlässig. Mit Programm! Kostenpunkt: so um die 5.-€

Wenns was Besseres sein soll: siehe den Sensoren-Thread, da beschreibe ich einen preiswerten (ca. 30.-€) Sensor, der geht aber auf 1/1000 mm genau!

Tu Dir was Gutes und bau was Ordentliches an Deine Drehbank.

Gruß,

Harley
Benutzeravatar
Wurstblinker
Beiträge: 601
Registriert: Di 13. Sep 2016, 21:09
Wohnort: weit West

Re: Der AVR-/ARDUINO-Faden

Beitrag von Wurstblinker »

Also sollte da oben
int data[3];
stehen.

Das ist mir als erstes aufgefallen. Kann also noch etwas mehr nicht stimmen.
Anse

Ich werd verrückt, genau das war das Problem !
Hätte ich selbst wohl nie gefunden,
vielen dank @ Anse und Blueloop
Für eure Hilfe

Endlich macht die Anzeige was sie soll "!
@harlay
habe den Sensoren Thread gelesen, die Idee mit der Maus spukt aber schon ein paar Monate länger….
Für das antüddeln an den Schlitten hab ich ne schöne Schiene auffem Schrott gefunden die wohl mal für was ähnliches gedacht war.
Meine versuche mit Maus und Messuhr waren überraschend gut .
Da die Drehe eh 3-4 hundertstel schlag und Zehnteleinteilung auf den Skalenringen hat bin ich sicher damit hinzukommen bis mir evtl. was besseres über den weg läuft.

bye , Andi
Anse
Beiträge: 2278
Registriert: Mo 12. Aug 2013, 21:30
Wohnort: Bühl (Baden)

Re: Der AVR-/ARDUINO-Faden

Beitrag von Anse »

Ich werd verrückt, genau das war das Problem !
Hätte ich selbst wohl nie gefunden,
Compiler für andere Sprachen hätte diesen Fehler gefunden. C-Compilern ist so was relativ egal.

In welcher Einheit wird die Position angezeigt?
Benutzeravatar
Wurstblinker
Beiträge: 601
Registriert: Di 13. Sep 2016, 21:09
Wohnort: weit West

Re: Der AVR-/ARDUINO-Faden

Beitrag von Wurstblinker »

Im moment noch in Pixel.

Die Versuchs Maus hat 800 dpi also komme ich so um die 3 hundertstel Auflösung.

Hier trollt aber auch noch ne Logilink Kabelmaus mit 2000 dpi rum die wahrscheinlich später zum Einsatz kommt.
Matt
Beiträge: 6084
Registriert: So 24. Aug 2014, 21:22

Re: Der AVR-/ARDUINO-Faden

Beitrag von Matt »

boh, Gray -Binar Umwandelcode macht mir fertig.

sollte 25bit Gray ins binär umgewandelt werden, es tut irgendwie, aber NICHT binär.

was ich da gemacht habe, MSB von Gray direkt ins binär übertrage, danach binäre MSB mit eine kleinere Stelle von Gray über XOR verküpfen und Ergebnisse zu kleinere binäre Stelle übertragen.

ENCdata = Graycode aus Encoder
result= binäre Ergebnisse

Code: Alles auswählen

result = (ENCdata & 0x8000 );
	
		
		result =  (ENCdata & 0x4000) ^ (result>>1);
		result =  (ENCdata & 0x2000) ^ (result>>1);
		result =  (ENCdata & 0x1000) ^ (result>>1);
		
		result =  (ENCdata & 0x0800) ^ (result>>1);
		result =  (ENCdata & 0x0400) ^ (result>>1);
		result =  (ENCdata & 0x0200) ^ (result>>1);
		result =  (ENCdata & 0x0100) ^ (result>>1);
		
		result =  (ENCdata & 0x0080) ^ (result>>1);
		result =  (ENCdata & 0x0040) ^ (result>>1);
		result =  (ENCdata & 0x0020) ^ (result>>1);
		result =  (ENCdata & 0x0010) ^ (result>>1);
		
		result =  (ENCdata & 0x0008) ^ (result>>1);
		result =  (ENCdata & 0x0004) ^ (result>>1);
		result =  (ENCdata & 0x0002) ^ (result>>1);
		result =  (ENCdata & 0x0001) ^ (result>>1);
Matt
Beiträge: 6084
Registriert: So 24. Aug 2014, 21:22

Re: Der AVR-/ARDUINO-Faden

Beitrag von Matt »

argh, jetzt weiss, ich dass diese Code kacke ist, "result" wird immer übergeschrieben.. so war es..

aber falls ihr bessere Gray - Binär Code Wandler hat, her damit.

Grüss
Matt
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Der AVR-/ARDUINO-Faden

Beitrag von Fritzler »

Selbst mit veroderung kommt da Käse raus, da du auch die Bits zu früh ausmaskierst, dass darf erst nach dem XOR passieren, also so hier:

Code: Alles auswählen

int gray_to_bin(int ENCdata){
    
    int result = ENCdata & 0x8000;
    result |= (ENCdata ^ (result >> 1)) & 0x4000;
    result |= (ENCdata ^ (result >> 1)) & 0x2000;
    result |= (ENCdata ^ (result >> 1)) & 0x1000;
    
    result |= (ENCdata ^ (result >> 1)) & 0x0800;
    result |= (ENCdata ^ (result >> 1)) & 0x0400;
    result |= (ENCdata ^ (result >> 1)) & 0x0200;
    result |= (ENCdata ^ (result >> 1)) & 0x0100;
    
    result |= (ENCdata ^ (result >> 1)) & 0x0080;
    result |= (ENCdata ^ (result >> 1)) & 0x0040;
    result |= (ENCdata ^ (result >> 1)) & 0x0020;
    result |= (ENCdata ^ (result >> 1)) & 0x0010;
    
    result |= (ENCdata ^ (result >> 1)) & 0x0008;
    result |= (ENCdata ^ (result >> 1)) & 0x0004;
    result |= (ENCdata ^ (result >> 1)) & 0x0002;
    result |= (ENCdata ^ (result >> 1)) & 0x0001;
    
    return result;
}
Oder schön als Schleife mit später auch mal mehr oder weniger Bit gehen:

Code: Alles auswählen

#define GRAYBITS 16
int gray_to_bin(int ENCdata){

	 int i, result = ENCdata & (1 << (GRAYBITS-1));
	 for (i = GRAYBITS - 2; i >= 0; i--){
	 	result |= (ENCdata ^ (result >> 1)) & (1 << i);
	 }
	 return result;
}
Matt
Beiträge: 6084
Registriert: So 24. Aug 2014, 21:22

Re: Der AVR-/ARDUINO-Faden

Beitrag von Matt »

so kommt vor, dass ich an daran zerbricht und nicht mehr so klar denkt , dazu verarscht Encoder mir mit invertierende Gray-Code...(mein Fehler, SSI Datenleitung vertauscht)


diese Code funktioniert ja, aber Länge von 16 bit beschränkt, auch wenn ich von "int" zu "long" abgeändert habe, ist Ergebnisse immernoch auf 16 bit beschränkt. Merkwürdig oder kleine krasse Denkfehler hab ich ?.. (result, ENCdata ist bereits mit "uint32_t" definiert.)

Das Danke hast du aber klar verdient .

Grüss
Matt
Name vergessen
Beiträge: 3261
Registriert: Mo 12. Aug 2013, 19:47

Re: Der AVR-/ARDUINO-Faden

Beitrag von Name vergessen »

Es ist nicht unüblich, daß bei µCs ints 16 oder sogar nur 8 Bit lang sind, da hilft nur beim Compiler nachzuschlagen, oder generell uintXX_t nehmen, da weiß man (meistens...), was man bekommt. Evtl. tut's auch "long long", falls das definiert ist. Und ich würde immer "unsigned" für sowas nehmen, bzw. die Signedness generell explizit vorgeben, auch da haben Compiler machmal unterschiedliche Ansichten und können sinnvoller warnen.
Benutzeravatar
Fritzler
Beiträge: 12579
Registriert: So 11. Aug 2013, 19:42
Wohnort: D:/Berlin/Adlershof/Technologiepark
Kontaktdaten:

Re: Der AVR-/ARDUINO-Faden

Beitrag von Fritzler »

Jetz bin ich verwirrt, sind es denn nun wirklich 25Bit vom Encoder oder ist das nen vertipper und es sind 15 bit?

Ein int ist übrigens immer mind 16bit breit, 8bit int geht laut c standard nicht.
Daher ist es, wie bereits angesprochen, immer eine gute Idee stdint.h zu verwenden.
http://www.cplusplus.com/reference/cstdint/

Für mehr BIts muss mein Code anders lauten, denn aufm AVR GCC kann normalerweise nur 16Bit weit geschoben werden, weil die 1 bei 1<<x als int angelegt wird.

Code: Alles auswählen

#define GRAYBITS 25
uint32_t gray_to_bin(uint32_t ENCdata){

    uint32_t i, result = ENCdata & (1 << (GRAYBITS-1));
    for (i = GRAYBITS - 2; i >= 0; i--){
       result |= (ENCdata ^ (result >> 1)) & (((uint32_t)1) << i);
    }
    return result;
}
Matt
Beiträge: 6084
Registriert: So 24. Aug 2014, 21:22

Re: Der AVR-/ARDUINO-Faden

Beitrag von Matt »

Hi

Ja, es ist bereits geschrieben, dass Encoder 25bit Gray-Code raushaut. fünfzwanzig.
das stdint.h ist bereits drin. Ist Standard, den packe ich immer rein, auch wenn mal nicht gebraucht wird.(was sehr selten passiert :-) )

Das Hinweis mit n = int (16bit) beim Bitverschieben ist GOLD wert. D

Genauso hat mir Freund hingewiesen, dass beim C so ist : solange Ergebnisse nicht NULL ist , ist es dann "true" (z.B. auf gesetzte Bit prüfen, " ((PIN & 0x01) == 0x01) ist genauso (PIN & 0x01)
Benutzeravatar
Bauteiltöter
Beiträge: 254
Registriert: So 11. Aug 2013, 17:37

Re: Der AVR-/ARDUINO-Faden

Beitrag von Bauteiltöter »

Fritzler hat geschrieben:Ein int ist übrigens immer mind 16bit breit, 8bit int geht laut c standard nicht.
Stimmt, aber der GCC bietet die Option "-mint8" an, mit der wird ein "Int" 8 Bits lang. long ist dann 16 Bits und long long 32Bit.
Aber passt, auf die Option ist BÖSE, da sie nicht auf dazu gelinkte Bibliotheken (wie die avr-libc) wirkt. Somit kann man keine FUnktion aus der libc mehr benutzen! Ist für die Praxis also komplett ohne Bedeutung.

anstatt der langen Casts bei Shifts kann man auch ein UL (unsigned long) an die 1 setzen.
Also statt

Code: Alles auswählen

(uint32_t)1 << 30

geht auch

Code: Alles auswählen

1UL << 30
Gibt weniger Zeichen zu Tippen und ist auch gut lesbar :)
Matt
Beiträge: 6084
Registriert: So 24. Aug 2014, 21:22

Re: Der AVR-/ARDUINO-Faden

Beitrag von Matt »

edit.. meine erste Code für Gray-Binar umwandeln ist auch noch falsch, krasse Denkfehler hab ich gemacht: irgendwie unbewusst hab ich EINE HEXdezimale Stell als 8bit breit gehaltet. Merkwürdigweise nur diese Stelle.
@ Fritzler, ist das deswegen , dass du denkt, dass ich Tippfehler gemacht habe (15bit statt 25bit)

verkürzte Varianten von (uint32_t)1 ist 1UL, ist auch korrekt, eben getestet, auch für gut befundet :-)

so perfekt bin ich mit C auch noch nicht..

aber für andere Leute, der einfache Binäre-BCD Umwandlung haben wollte: hab was für euch, es lässt beliebig kaskadieren bzw verkürzen.
(ist aus trollnest.net ähm µC.net, von mir angepasst)

Code: Alles auswählen

void bin_to_bcd(uint32_t value, unsigned char bcd[10])
{
    bcd[0] = value % 10;
    value=value/10;
  
    bcd[1] = value % 10;
    value=value/10;

    bcd[2] = value % 10;
    value=value/10;

    bcd[3] = value % 10;
    value=value/10;

    bcd[4] = value % 10;
    value=value/10;

    bcd[5] = value % 10;
    value=value/10;

    bcd[6] = value % 10;
    value=value/10;

    bcd[7] = value % 10;
    value=value/10;

    bcd[8] = value % 10;
    value=value/10;

    bcd[9] = value % 10;
    value=value/10;
}
Antworten