Seite 26 von 31

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mo 3. Jan 2022, 18:48
von Anse
Um was für ein Gerät handelt es sich? Und was meinst Du mit Zählweise?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 11. Jan 2022, 16:53
von Weisskeinen
ch_ris hat geschrieben: So 2. Jan 2022, 07:17

Code: Alles auswählen

((100/3.6)/(1.95))*(43/16)*26
= 995,37037037037037037037
das ist die Ausgabe vom PC calculator.
Auf dem Nano ausgeführt ergibt das glatt 1000, bzw 1000 ergibt 100.

Code: Alles auswählen

return ((((float) a/ ( b* c)) * d)* 3.6);
Alle Werte sind float ausser a, weiteres casten ändert nix.

das mir der Präzision hab ich schon mal gelesen, daher bin ich eh geizig mit float.
hier ist's mir "egal" das ist nur ein Nebenprojekt.
Komisch, ich habe das mal mit diesem Rechner auf 32-Bit-Genauigkeit nachgerechnet: http://weitz.de/ieee/
und bin auf 995.3703 gekommen. Und auch bei 16-Bit-Genauigkeit komme ich immer noch nur auf 995.5. Da muss was anderes im Argen sein...

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 11. Jan 2022, 17:34
von ch_ris
Stimmt, hab's für sich allein mal rechnen lassen, mit korrektem Ergebnis,
da muss im Code was verbogen sein. Danke für den Hinweis.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 5. Mär 2022, 10:11
von Tobi
Moin,
ich sitze gerade vor einem Tiny84a mit ATTinyCore in der Arduino IDE1.8.19.
Gewünscht ist es, mit dem Auslösen des Int0 den Pin7 (OCOB) auf 1 zu setzen und den Timer0 zu starten. Wenn der Timer den Vergleichswert in OCR0B erreicht hat, soll er den Pin7 wieder auf low setzen.
Laut dem Datenblatt müsste der Ausgang auch vom Timer überschrieben werden:
" • Bits 5:4 – COM0B1, COM0B:0: Compare Match Output B Mode
These bits control the Output Compare pin (OC0B) behavior. If one or both of the COM0B1:0
bits are set, the OC0B output overrides the normal port functionality of the I/O pin it is connected
to."
Die LED an Pin10 dient nur der Kontrolle der ISR, die funst auch. Jedoch setzt der Timer nie den Pin 7 wieder auf low zurück, warum? Wenn ich testweise Bit COM0B1 im Timerregister auf 1 setzte, und damit das toggeln aktiviere, toggelt er auch wie ich das erwarte. Grundsätzlich läuft der Timer also.
Wer kann helfen?

Code: Alles auswählen

bool led = 0;

void setup() {

  sei();                      //interupts aus

  pinMode(10, INPUT_PULLUP);  //interrupt eingang

  pinMode(7, OUTPUT);         //tiny pin 6, oc1b
  pinMode(10, OUTPUT);        //tiny pin 2, led

  GIMSK = _BV(INT0);          //ext interupt an int0, pin 5
  MCUCR = _BV(ISC01);         //interupt bei fallender flanke

  sei();                      //interrupts an
}



void loop () {

  TCCR0A = _BV(COM0B1) | _BV(WGM01);  // OC0B = 0 bei match + ctc mode
  TCCR0B = _BV(CS01) | _BV(CS00) ;    //vorteiler =8      
  OCR0A  = 0xff;                      //zählen bis 255
  OCR0B  = 0xff;                      //vergleichswert = 255
  GTCCR = _BV(PSR10) | _BV(TSM);      //timer sync mode + prescaler reset


  while (1) {
    digitalWrite(10, led);
  }  
}



ISR(INT0_vect)
{
  led = !led;             //debug led toggeln
  GTCCR = ~_BV(PSR10);    //start timer
  digitalWrite(7, HIGH);  //ausgang setzen
}

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 5. Mär 2022, 10:24
von andreas6
Ich sehe keinen Befehl, der den Ausgang auf Low schaltet. Vergessen?

MfG. Andreas

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 5. Mär 2022, 10:47
von Tobi
Das sollte der Timer machen, OCOB ist Pin7:
timer.PNG

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 8. Mär 2022, 20:10
von Weisskeinen
Eine Lösung habe ich jetzt auch nicht, aber der Programmierstil ist seltsam. In loop() gehört nur noch das, was dauernd ausgeführt werden soll, sonst nichts. Die Timer-Einstellung gehört noch in setup(). Wenn außer den Interrupts nichts ausgeführt wird, bleibt die Funktion loop() eben leer. Ganz besonders gehört da keine weitere Endlosschleife rein.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 8. Mär 2022, 21:10
von Tobi
Ja, das stimmt wohl. Das kommt daher das der Hauptteil des eigendlichen Programms testweise rausgeflogen.
Zwei Sachen sind mir jetzt selber aufegafallen:
-Im Setup steht zweimal sei() anstatt cli(), copy-paste Fehler
-Ich kann den OC0B nicht über das PORTB Register setzen, weil der Pin in diesem Fall komplett von diesem abgetrennt ist

Stattdessen konfiguriere ich nun den Timer in der ISR als "set OC0B on match" und setze dann das FOC0B-Bit. Damit wird ein match erzwungen und OC0B wird auf 1 gesetzt.
Dann setze ich den Timer wieder auf "clear OC0B on match" und starte den Timer. Aber der Timer setzt den Pin nicht zurück :(

SPI-DAC gesucht, günstig bitte

Verfasst: Sa 12. Mär 2022, 22:06
von Hightech
Moin,
ich suche einen günstigen SPI-DAC, so was wie den LTC1286, aber in bezahlbar.
Weiß da jemand was günstiges oder hat gar zu viele und möchte die gerne verkaufen ?

ich tausche auch gerne gegen AD558 ;)

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 12. Mär 2022, 22:31
von IPv6
Ein LTC1286 ist aber ein ADC?

Was soll es denn nun sein, was für Anforderungen, was für eine Anwendung,...?

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 13. Mär 2022, 00:04
von Hightech
IPv6 hat geschrieben: Sa 12. Mär 2022, 22:31 Ein LTC1286 ist aber ein ADC?

Was soll es denn nun sein, was für Anforderungen, was für eine Anwendung,...?
Ach, shit. Ein DAC soll es sein.

Der AD558 hat zum Beispiel einen Verstärker mit eingebaut, so das man prima eine beliebige Ausgangsspannung bekommt.
So etwas wäre gut.
10-12 Bit reichen mit völlig, es soll ja nur eine Steuerspannug erzeugt werden.

Obwohl ein 10k SPI-Poti IC wäre ja auch praktisch.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 13. Mär 2022, 00:20
von IPv6
So wirklich folgen kann ich dir immer noch nicht.
Wenn ein AD558 gut wäre, wieso bietest du den dann zum tausch an?

Eine sich nur langsam ändernde Steuerspannung erzeugst du am einfachsten mit einer tiefpassgefilterten PWM vom Microcontroller.
Hinten den PWM Ausgang kommt dazu ein passendes RC Glied und ein LM358. Der erste OPV als Spannungsfolger um das RC Glied nicht zu belasten, der zweite OPV verstärkt dann auf deine Wunschspannung wenn z.B. ein 0-10 V Signal gefragt ist.
Sollte das einfache RC Glied nicht gut genug filtern kann man das Filter auch steilflankiger als Sallen-Key um den OPV aufbauen.

So habe ich schon einige Umsetzer für DMX auf 0-10 V gebaut, funktioniert wunderbar solange sich die Steuerspannung nur einigermaßen träge ändert.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 13. Mär 2022, 00:28
von Hightech
IPv6 hat geschrieben: So 13. Mär 2022, 00:20 So wirklich folgen kann ich dir immer noch nicht.
Wenn ein AD558 gut wäre, wieso bietest du den dann zum tausch an?
Weil das ein DAC mit 8-Bit Bus ist.

Ich wollte einen SPI oder I2C DAC, weil ich mit dem Timer auf Kriegsfuß stehe. Aber vielleicht versuche ich das doch mal mit Tiefpass und OP.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 13. Mär 2022, 00:32
von IPv6
Stimmt, der AD558 versteht kein SPI.

Versuch das mal mit einer gefilterten PWM. Mir hat damals die ultrasimple Ausführung mit Filter 1. Ordnung gereicht, aber ich stelle gerade fest, dass mit etwas mehr Bauteilaufwand (4 Widerstände, 4 Kondensatoren) und dem Dual-OPV ein Filter 4. Ordnung möglich gewesen wäre. Damit sollte die Ausgangsspannung mehr als ausreichen glatt werden.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 13. Mär 2022, 01:17
von Hightech
IPv6 hat geschrieben: So 13. Mär 2022, 00:32 Stimmt, der AD558 versteht kein SPI.

Versuch das mal mit einer gefilterten PWM. Mir hat damals die ultrasimple Ausführung mit Filter 1. Ordnung gereicht, aber ich stelle gerade fest, dass mit etwas mehr Bauteilaufwand (4 Widerstände, 4 Kondensatoren) und dem Dual-OPV ein Filter 4. Ordnung möglich gewesen wäre. Damit sollte die Ausgangsspannung mehr als ausreichen glatt werden.
Ja, üben, üben, üben.
Ich muss mal einen Filter bauen. Eine einfache RC-Kombination ist furchtbar ungeeignet als Ausgang für einen 0-10V Frequenzumrichter.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 13. Mär 2022, 10:31
von IPv6
Furchtbar ungeeignet ist das sicher nicht, wenn das Signal mit einem OPV gepuffert wird. Aber muss ja eh sein wenn es 0-10 V braucht.
Da sich mein Signal nur recht langsam änderte hatte das RC Filter eine Grenzfrequenz von 1 Hz. Der Arduino macht typischerweise eine PWM mit ca. 500 Hz. Die Grundschwingung der PWM wird dann schon um etwa Faktor 500 gedämpft. Die wenigen mV Restwelligkeit werden den FU Eingang wohl auch nicht stören.

Re: SPI-DAC gesucht, günstig bitte

Verfasst: Mo 14. Mär 2022, 21:51
von vobs
Hightech hat geschrieben: Sa 12. Mär 2022, 22:06 ich suche einen günstigen SPI-DAC, so was wie den LTC1286, aber in bezahlbar.
Microchip hat da eine nette Auswahl, z.B.
MCP4901/4911/4921 oder MCP4921/4922 oder MCP4802/4812/4822.
Habe ich vor ein paar Jahren mal bei Reichelt bestellt, die sollten also nicht so schwer zu beschaffen sein.
Ob die jetzt mit Deinem ADC vergleichbar sind, musst Du selber beurteilen, mirr fehlen da die Kriterien.

Grüßle
Volker

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mo 14. Mär 2022, 22:29
von Alexander470815
Man könnte sich wohl auch die 10V die der FU selber raus gibt schnappen und mit dem Microcontroller zwei Optokoppler bespaßen.
Die Optokoppler schalten dann zwischen GND und 10V hin und her, noch ein Tiefpass dahinter und schon hat man die 0-10V oder halt 0,5V-9,5V aber das kann man ja skalieren im FU.
Nebenbei hat man das ganze auch noch gegeneinander isoliert.

Manche FUs können auch ein Frequenzsignal als Sollwertquelle verarbeiten, das lässt sich ja auch recht einfach erzeugen.
Für genügend Bandbreite kann man die PWM ja ein bisschen schneller machen als das was Arduino von alleine mitbringt...
Unbenannt.jpg

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 15. Mär 2022, 07:35
von Hightech
Schade, die standart DACs können am Ausgang alle nur 5,5V.
Die anderen gibt es auch, aber dann zu Mondpreisen.

Im Moment gebe ich die PWM auf einen Transistor, welcher einfach die 10V über einen Widerstand auf 0V zieht.

Ich muss da mal einen aktiven Tiefpass hin bauen, denn so ist das furchtbar unlinear.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 15. Mär 2022, 07:59
von Fritzler
Um einen Opamp mit 12 bis 15V Versorgung wirste nicht wirklich drumrum kommen.
Der ist dann direkt Verstärker und Tiefpass 2. Ordnung.

Die Herren Sallen und Key lassen grüßen:
http://sim.okawa-denshi.jp/en/OPseikiLowkeisan.htm

Eine Verstärkung gibts wenn der Opamp nicht als Spannungsfolger betrieben wird.
(runter scrollen bem Link, dann gibts auch dafür nen Berechner)

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mo 21. Mär 2022, 11:04
von ch_ris
hab gerade BurnOmat 2.2.0 auf LMDE4(linux mint) installiert.
Bei den avrdude options ist die programmer option leer, gibt nix zur auswahl.
avrdude (6.3) problem? fehlt da eine Lib?

edit. die pfade waren verbogen, ach Linux...
das ach ist mehr der ungewohnten Ordnerstruktur geschuldet, alles einfach lösbar...

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 23. Mär 2022, 21:58
von Hightech
Mit einem TS912 R2R OP hab ich meine 0-10V bei 490Hz eigentlich schön raus bekommen.
Der wird mit 12V bespielt.


Bild

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 20. Mai 2022, 09:45
von ch_ris
ich benutze zwei wege einen nano zu programmieren.
Sloeber IDE, die letzlich die Arduino umgebung /avrdude benutzt, sollte also gleich sein.
manchmal klappt es nicht, ich muss dann die andere 328p Option benutzen (old bootloader ja/nein), ja nach nano.
oder
mit dem Fon mittels app: Arduino Hex Upload. hier das gleiche Spiel, nur das keine old bootloader Option da ist.
wenn ich stattdessen Uno wähle, klappt der upload.
Programm läuft auch. Nano/Uno egal?
oder doch nur scheinbar? kann das irgendwelche Probleme machen?
bin verunsichert weil die IDE bei Wechsel der Option komplett neu kompiliert.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 20. Mai 2022, 11:15
von IPv6
Das hängt mit dem Bootloader zusammen.
Für die Nanos wurde der 2018 mal auf Optiboot umgestellt, der ist kleiner und arbeitet mit einer höheren Baudrate.
Der Chinese liefert seine Nanos aber immernoch mit dem alten Bootloader aus, daher muss für die billigen Klone meist die "old bootloader" Option ausgewählt werden.
Mit was für eine Bootloader der Uno daherkommt weiß ich nicht auswendig, scheinbar aber mit dem gleichen, der auch auf so manchen Nanos daherkommt, sonst würde der Upload bei dir nicht klappen.

Da Uno und Nano die gleichen Controller nutzen ist es im Prinzip egal, mit welcher Option du dein Programm hochlädst.

Wenn du es "schön" machen willst kannst du auch auf deine Boards den neuen Bootloader spielen, dazu brauchst du nur einen ISP Programmer (oder einen zweiten Arduino, der als ISP Schnittstelle verwendet wird).
Dann kannst du auf die "old bootloader" Option verzichten und hast die Vorteile von Optiboot (die aber zugegebenermaßen oftmals eher nicht so entscheidend sind).

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 20. Mai 2022, 11:19
von Später Gast
Der Nano hat glaub paar mehr pins, wenn die benutzt werden müsste der kompiler meckern bei uno als eingestelltes Board?

Sonst: wenns läuft, läufts?
Vllt für sicherheitskritische Sachen nur den PC nehmen, oder halt lernen wie man bootloader brennt und alle Boards bei Erhalt auf den neuen umflashen.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 20. Mai 2022, 13:25
von ch_ris
stimmt, der hat 2 Analog pins mehr, aber kompiliert hab ich eh mit nano option.
dank euch, dann lass ich's erst mal so, bei gelegenheit bau ich mal nen 2x3 stecker für den programer.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 22. Mai 2022, 00:08
von Toni
ich habe einen ATTINY13A, für den ich im Arduino Programm ein paar Assembler-Zeilen einfügen möchte.

wenn ich z.B. DDRB setzten möchte

Code: Alles auswählen

asm volatile 
  (
 "ldi r16, 0b00111111 \n"
 "out DDRB, r16 \n")
kommt folgende Fehlermeldung:
"...Tiny13-button-led-ASM-Test.ino:52: undefined reference to `DDRB'"

Arduino kennt ja DDRB, aber warum nicht innerhalb vom Assembler-Schnipsel?

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 22. Mai 2022, 09:02
von Jannyboy
Toni hat geschrieben: So 22. Mai 2022, 00:08 ich habe einen ATTINY13A, für den ich im Arduino Programm ein paar Assembler-Zeilen einfügen möchte.

wenn ich z.B. DDRB setzten möchte

Code: Alles auswählen

asm volatile 
  (
 "ldi r16, 0b00111111 \n"
 "out DDRB, r16 \n")
kommt folgende Fehlermeldung:
"...Tiny13-button-led-ASM-Test.ino:52: undefined reference to `DDRB'"

Arduino kennt ja DDRB, aber warum nicht innerhalb vom Assembler-Schnipsel?
Weil C/C++ defines nicht direkt im Assembler bekannt sind.
Und der ASM-Teil vor dem C/C++ Teil übersetz verwenden. Die genaue Reihenfolge sieht in der GCC Doku. Ich bin der Meinung das war defaultmässig ASM -> C -> C++

Im ASM gibt es dafür ein Prefix. Ich glaube du muss __DDRB schreiben.

Grüße Jan

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 22. Mai 2022, 20:08
von Toni
das mit Konstanten in ASM übernehmen habe ich nicht hinbekommen.
Die Register DDRB und PORTB direkt adressieren funktioniert aber

Hier ist ein Mischmasch mit ASM-Fetzen. LED an PB2 blinkt, solange Taster an PB4 gedrückt ist:

Code: Alles auswählen

const int buttonPin = 2;     // the number of the pushbutton pin
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(PB4, INPUT);
  pinMode(PB4, INPUT_PULLUP); //configure pin 2 as an input and enable the internal pull-up resistor

  // initialize the LED pin as an output:
  // DDRB equ 0x17
  asm
  (
    // alternativ: "ldi r16, 0b00001000 \n"
    "ldi r16, 0x08 \n"
    "out 0x17, r16 \n") // DDRB Bit 3 setzen
  ;
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(PB4);

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == LOW) {
    // turn LED on:
    // PORTB equ 0x18
    asm  (
      "ldi r16, 0b00001000 \n"
      "cbi 0x18, 3 \n" 		//clear Bit PB3
    );

    delay(500);
    // turn LED off:
    //    digitalWrite(PB3, HIGH);
    asm  (
      "ldi r16, 0b00001000 \n"
      "sbi 0x18, 3 \n" 		//set Bit PB3
    );

    delay(100);
  } else {
    // turn LED off:
    digitalWrite(PB3, LOW);
  }
}

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 3. Jun 2022, 22:29
von Toni
das mit dem ATTINY habe ich hinbekommen: ich programmiere den komplett in Assembler mit Editor Gerd's AVM Simulator http://www.avr-asm-tutorial.net/avr_sim ... l#download, und schiebe es über einen USBasp https://www.fischl.de/usbasp/ mittels AVRDUDE auf den Tiny.

Aber zum Arduino Uno habe ich noch eine Frage. Ich möchte einen Drehzahlmesser bauen, und dazu diesen Code gefunden + angepasst:

Code: Alles auswählen

//DIY Tachometer to Measure Accurate RPM using Arduino
//DIY Tachometer to Measure Accurate RPM using Arduino
//This code is published by https://www.circuitschools.com
//Attribution required to republish.
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Angabe der erforderlichen Pins

 
// Create the lcd object address 0x27(get it from i2cscanner) and 16 columns x 2 rows 
// LiquidCrystal_I2C lcd (0x27, 16,2); //
float value=0;
float rev=0;
int rpm;
int oldtime=0;
int newtime;
void isr() //interrupt service routine
{
rev++;
}
void setup()
{
lcd.begin(16, 2); // Starten der Programmbibliothek.
// Turn on the backlight on LCD. 
//lcd. backlight ();
attachInterrupt(digitalPinToInterrupt(2),isr,RISING); //attaching the interrupt
}
void loop()
{
 
delay(1000);
detachInterrupt(0); //detaches the interrupt
newtime=millis()-oldtime; //finds the time 
int wings= 1; // no of wings of rotating object, for disc object use 1 with white tape on one side
int RPMnew = rev/wings; //here we used fan which has 3 wings
rpm=(RPMnew/newtime)*60000; //calculates rpm
oldtime=millis(); //saves the current time
rev=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Drehzahl U/Min :");
lcd.setCursor(0,1);
lcd.print( rpm);
lcd.print("");
lcd.print(" ");
attachInterrupt(digitalPinToInterrupt(2),isr,RISING);
}
Die Drehzahl sollte aus steigenden Flanken an Pin 2 berechnet, und angezeigt werden. Das Display zeigt aber immer "0" an. Evtl werden die Interrupts nicht ausgelöst??? Gibt's da noch eine extra Einstellung oder Fuses die gesetzt werden müssen?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 3. Jun 2022, 22:55
von virtexultra
Ich vermisse eine Zeile die den pinMode setzt. Kann aber sein das das per Default auf Input steht und somit irrelevant ist.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 3. Jun 2022, 23:22
von Derkiki
Zumindest die Variable Rev sollte "volatile" deklariert werden, ansonsten schmeißt der Compiler sie ersatzlos raus.....
Weiterhin: "detachinterrupt" scheint zumindest kein Arduino zu sein.
Ich würde das Aktivieren und deaktivieren des Interrupts über das globale SEI(); bzw CLI(); probieren, wenn das LCD nicht auch irgendwelche Interrupts benötigt.

Ansonsten Mal die Variable "Rev" in einem Timer-Interrupt hochzählen lassen zum Testen.
Vielleicht hilft's...

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 4. Jun 2022, 10:10
von ch_ris
imho.
rev muss volatile.edit-hast ja schon geschrieben...
denn rest versteh ich wenig. was soll das ganze zeug im mainloop?
selbst mit millis (und nicht mit timer) geht das doch einfacher?:

Code: Alles auswählen

	/////////MotorZustand//////////////////
	tt = millis() - rpmTimeStamp;
	if (tt >= 200) {
		
			rPM = (float) rpmTicks * (float) 30000 / (float) tt;
			rpmTimeStamp = millis();
			rpmTicks = 0;
			blabla....
hier nur mal grad rauskopiert der schnipsel.

edit. erst wird oldtime gesetzt, dann das zeitaufwändige lcd zeug gemacht, dann erst der interupt wieder angeschaltet?
und das soll das tun?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 4. Jun 2022, 11:57
von Toni
Danke für euren Input. Leider kenne ich mich mit Arduino Sketch / C++ zu wenig aus -> ich hab's mit den Änderungen nicht hinbekommen :(

Hier habe ich ein anderes Programm gefunden https://srituhobby.com/ir-infrared-spee ... ed-sensor/, und das für meine Zwecke modifiziert (u.a. für dieses Display: https://www.berrybase.de/lcd/keypad-shi ... nlEALw_wcB ).
Das funktioniert jetzt :)
umin.jpg

Die ursprünglichen Zeilen habe ich als // drin gelassen.

Code: Alles auswählen

#include <LiquidCrystal.h>
//#include <LiquidCrystal_I2C.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Angabe der erforderlichen Pins
// LiquidCrystal_I2C lcd (0x27, 16, 2); 

const byte PulsesPerRevolution = 1;
const unsigned long ZeroTimeout = 1000000;
const byte numReadings = 2;

volatile unsigned long LastTimeWeMeasured;
volatile unsigned long PeriodBetweenPulses = ZeroTimeout + 1000;
volatile unsigned long PeriodAverage = ZeroTimeout + 1000;
unsigned long FrequencyRaw;
unsigned long FrequencyReal;
long Frequenz;
unsigned long RPM;
unsigned int PulseCounter = 1;
unsigned long PeriodSum;

unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;
unsigned long CurrentMicros = micros();
unsigned int AmountOfReadings = 1;
unsigned int ZeroDebouncingExtra;
unsigned long readings[numReadings];
unsigned long readIndex;  
unsigned long total; 
unsigned long average;

void setup()
{
lcd.begin(16, 2); // Starten der Programmbibliothek.
lcd.setCursor(0,0); // Angabe des Cursorstartpunktes oben links.
  //lcd.print(""); // Ausgabe des Textes "Nachricht".

  attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, RISING);
  delay(1000);
}
 
void loop()
{
lcd.setCursor(12,1); // Bewegt den Cursor in Zeile 2 (Line0=Zeile1 und Line1=Zeile2) and die Stelle "12".

  LastTimeCycleMeasure = LastTimeWeMeasured;
  CurrentMicros = micros();
  if (CurrentMicros < LastTimeCycleMeasure) {
    LastTimeCycleMeasure = CurrentMicros;
  }
  FrequencyRaw = 10000000000 / PeriodAverage;
  if (PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra) {
    FrequencyRaw = 0;  // Set frequency as 0.
    ZeroDebouncingExtra = 2000;
  } else {
    ZeroDebouncingExtra = 0;
  }
  FrequencyReal = FrequencyRaw / 10000;

  RPM = FrequencyRaw / PulsesPerRevolution * 60 ;
  RPM = RPM / 10000;
  Frequenz = RPM * 1000 / 60;
//  Frequenz = Frequenz * 1000;
//  Frequenz = 1000000 / Frequenz;
  total = total - readings[readIndex];
  readings[readIndex] = RPM;
  total = total + readings[readIndex];
  readIndex = readIndex + 1;

  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;

  lcd.setCursor(0, 1);
//  lcd.print("Period: ");
//  lcd.print(PeriodBetweenPulses);
//  lcd.print("\tReadings: ");
//  lcd.print(AmountOfReadings);
  lcd.print("\Freq.: ");
//  lcd.print(FrequencyReal);
  lcd.print(Frequenz);
  lcd.print("\mHz        ");
//  lcd.print("\tRPM: ");
//  lcd.print(RPM);
//  lcd.print("\tTachometer: ");
//  lcd.println(average);
  lcd.setCursor(0, 0);
  lcd.print("U/Min: ");
  lcd.print(RPM);
  lcd.print("     ");
}
void Pulse_Event() {
  PeriodBetweenPulses = micros() - LastTimeWeMeasured;
  LastTimeWeMeasured = micros();
  if (PulseCounter >= AmountOfReadings)  {
    PeriodAverage = PeriodSum / AmountOfReadings;
    PulseCounter = 1;
    PeriodSum = PeriodBetweenPulses;

    int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);
    RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);
    AmountOfReadings = RemapedAmountOfReadings;
  } else {
    PulseCounter++;
    PeriodSum = PeriodSum + PeriodBetweenPulses;
  }
}
EDIT: Programmfehler korrigiert: ungenutzte Stellen RPM auf Display löschen, Pulses per Rev=1, Ansprechschwelle herabgesetzt

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 11. Jun 2022, 22:50
von Toni
ich habe das Problem, dass sich beim ATTINY25 nicht wie gewohnt die HEX Datei über USBasp und AVRdude hochladen lässt.

Ausgangssituation: ATTINY13A lässt sich mit dieser Befehlszeile problemlos programmieren:

Code: Alles auswählen

avrdude -v -p t13 -b 1200 -c usbasp -P /dev/ttyS4 -D -F -U flash:w:/home/ich/Technik/Arduino/hex/Z-var-25.hex:i
beim ATTINY25 funktioniert diese Zeile nicht:

Code: Alles auswählen

avrdude -v -p t25 -b 1200 -c usbasp -P /dev/ttyS4 -D -F -U flash:w:/home/ich/Technik/Arduino/hex/Z-var-25.hex:i
da kommt die Fehlermeldung "avrdude: error: program enable: target doesn't answer"
Habe auch schon verschiedene andere Optionen probiert...

Über Arduino und Uno als Programmer funktioniert es ein Sketch hochzuladen, sowie Bootloader zu brennen. Aber damit bekomme ich halt nicht eine HEX hochgeladen

Dachte die Tinys 13A und 25 wären fast gleich. Weiß jemand wo der Unterschied beim Programmieren über AVRdude liegt, bzw. wie die Befehlszeile aussehen muss?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 11. Jun 2022, 23:02
von IPv6
Die Tinys sind auch wirklich nicht arg unterschiedlich.

Verstehe ich das richtig, dass du grundsätzlich was hochladen kannst, also z.B. das Blink-Beispiel oder sowas?
Wenn ja, aktiviere doch mal in den Einstellungen die vollständige Loggingausgabe in der IDE, dann zeigt es dir beim Upload genau den AVRDUDE Befehl an, den die IDE verwendet (und der ja dann gehen muss).
Den kopierst du dir und änderst den Pfad vom HEX-File vom temporäten Arduinoordner auf den Ort ab, wo dein gewünschtes HEX-File liegt.

Edit:
Du schreibst, dass du über Arduino (du meinst vermutlich die IDE?) und einem Arduino Uno als Programmer etwas auf den Tiny packen kannst.
Geht das auch mit dem usbasp? Den kann man auch zum IDE Programmupload verwenden.
Sonst eben mal das oben Geschriebene testen, da müsste dann ein AVRDUDE Befehl bei rauskommen, der als Programmer statt dem usbasp den Arduino (heißt dann glaube ich arduinoisp oder sowas) drinstehen hat.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 11. Jun 2022, 23:46
von Toni
Klasse Tipp, vielen Dank! Es hat funktioniert :D

Habe die ausführliche Ausgabe im Arduino aktiviert und die AVRdude Zeile rauskopiert und modifiziert.
Hiermit klappt es:

Code: Alles auswählen

avrdude -v -pattiny25 -cstk500v1 -P/dev/ttyACM2 -b19200 -U flash:w:/home/ich/Technik/Arduino/hex/Z-var-25.hex:i
Das funktioniert momentan nur mit dem Uno als ISP, und (noch) nicht mit dem USBasp, macht aber nix. Hauptsache es funzt erstmal!

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 30. Jun 2022, 15:21
von ch_ris
ist ja eher smalltalk...
ich hab folgende Drehzahl berechnung. in diesem fall will ich die zahl in 1/min.

Code: Alles auswählen

/////////MotorZustand//////////////////
	tt = millis() - rpmTimeStamp;
	if (tt >= 200) {
		//15.000 rpm * 2pulse / 60 = 500 pulse/sec (1/500= 2 mS Puls abstand)
		// 1500 rpm : 20 mS Puls abstand (tt >= 100 = 5 Pulse)
		//rpmTicks ist 8bit!!!-> tt max 500 (ueberlauf) TODO 16?
		//im recording tauchen nur 150er schritte auf,
		//dh. einfangen bei 200 geht zuverlässig, tt wird nie >200

		if (rpmTicks > 0) {
			rPM = (float) rpmTicks * (float) 30000 / (float) tt;
bei 1500 hab ich 10 pulse, bei 11 sinds 1650.
also schrittweite sind 150 u/min.
das ge-caste auf float kann ich mir doch komplett schenken oder.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 30. Jun 2022, 15:43
von Weisskeinen
Wahrscheinlich schon, aber für die Integerarithmetik brauchst du sicher 32bit-Zahlen.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 30. Jun 2022, 17:59
von ch_ris
oh, stimmt.
habs auch noch nicht angefasst,
damit nicht wieder so ein "ich dachte" fall draus wird :roll:

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 10:02
von ch_ris
einfach mal drüber zu quatschen hilft schon...
wenn ich anstatt ticks*30000/200ms,
ticks*19200/128 rechne,
kann ich das schubsen, und wenn mal 129ms draus würden, wär's scheinbar auch nicht so schlimm?
2022-07-01 09_55_45-Window.png
2022-07-01 09_55_45-Window.png (7.86 KiB) 1427 mal betrachtet
ich bekäme die werte fast doppelt so schnell bzw häufig, wär auch noch genauer.(wegen der Beschleunigung)
müsste dann so:
(uint32_t)(ticks * 19200)>>7;
oder wie ist die reihenfolge?vielleicht besser so:
((uint32_t)(ticks * 19200))>>7;

so oder so muss es getestet werden, vorher.

edit. neee bullshit. da ticks ja kleiner wird mit kürzerem zählfenster muss:
ticks*30000>>7

edit. casten...herrje
2022-07-01 11_29_54-sloeber44 - nano_test_mathetest.ino - Sloeber.png
letzes edit.
bei 128(millis) erhalte ich drehzahlstufen von 234 etwa.
scheint mir auch der beste Kompromiss zwischen Geschwindigkeit und Genauigkeit.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 12:02
von ch_ris
ist getestet, funktioniert...
bleibt eine Frage, funktioniert der cast:

Code: Alles auswählen

rPM = (uint32_t) rpmTicks * 30000 >> 7;
auch noch wenn mal der compiler ein update erhält, oder sonstwas..?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 13:22
von Alexander470815
Warum nicht einfach mit Interrupts und einem eigenen schneller laufenden Timer arbeiten?
Damit sollte sich eine viel feinere Auflösung erreichen lassen.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 16:28
von ch_ris
Alexander470815 hat geschrieben: Fr 1. Jul 2022, 13:22 Warum nicht einfach mit Interrupts und einem eigenen schneller laufenden Timer arbeiten?
Damit sollte sich eine viel feinere Auflösung erreichen lassen.
meinst du mit Timer Interrupt?
jetzt kommen die Impulse ja bereits von einem Interrupt.
könnt alle 10, oder so, pulse die Drehzahl rechnen lassen. dann passiert das um so öfter je schneller.
oder per Timer in fixen Zeit Intervallen, dann krieg ich ja (auch)Ungenauigkeiten durch "krumme Impulse", wenn die Zeit kurz ist.
Vielleicht geht da noch was? im Moment funktionierts halt, never touch...und so.

Kann auch schlecht abschätzen wie schnell die Drehzahländerung ist beim Moped.
Aus'm Bauch raus finde ich eine gute 10tel Sekunde schnell genug.
Die Schrittweite von 234Umin reicht auf jeden Fall hier.(durchstreich) sollte auch reichen.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 16:40
von Weisskeinen
ch_ris hat geschrieben: Fr 1. Jul 2022, 12:02 ist getestet, funktioniert...
bleibt eine Frage, funktioniert der cast:

Code: Alles auswählen

rPM = (uint32_t) rpmTicks * 30000 >> 7;
auch noch wenn mal der compiler ein update erhält, oder sonstwas..?
Sollte, ja. rpmTicks wird in eine 32-bit-Zahl gewandelt und mit einer Konstanten multipliziert. Dafür dürfte sie der Compiler ebenfalls als 32-bit-Zahl behandeln. Das 32-bittige Ergebnis wird dann um sieben Bit nach rechts geschoben und rPM zugewiesen. Je nach dem, was für einen Datentyp rPM hat, wird hier noch mal gecasted. Wenn ein zukünftiger Compiler das anders macht, hat der da einen Fehler und sollte sowieso nicht verwendet werden.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 16:59
von ch_ris
gut dann bleibts so. danke sehr.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 17:23
von Alexander470815
Ich dachte eher an einen Hardware interrupt der ausgelöst wird wenn es ein Signal gibt.
Dann schaut man einfach in das Zählregister eines Timers was drin steht und berechnet die Drehzahl.
Braucht man den Timer für sonst nichts setzt man den Zählerstand null für die nächste Messung.
Kann es dazu kommen das der Timer überläuft oder die Auflösung noch nicht reicht kann man ja über den overflow interrupt eine Variable hochzählen lassen die man dann mit einberechnet.
Über den Prescaler wählt man dann die Zählgeschwindigkeit entsprechend aus.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 17:37
von Bastelbruder
Ich hab jetzt den Anfang der aktuellen Geschichte nicht mitverfolgt. Aber vor 30 Jahren hatte ich mal ein "professionelles" Drehzahlmesserproblem. Es war ein Display für den Gokart, das außer der Drehzahl natürlich noch andere Kinkerlitzchen darstellen und zwischenspeichern konnte. Jedenfalls so lange sich das Kleinhirn nicht mit Jogging im Wald beschäftigt hat.

Hauptproblem war die Datenleitung vom "Steuergerät" zum Display. Vier Drähte und regelmäßige Aufhänger. Das Steuerteil wurde in der Nähe der CDI montiert und hat die Zündfunken problemlos detektiert. Der Controllertakt war Interruptgesteuert und hat in festen Zeitabständen seine Ergüsse per I2C zum Display geschoben. Die Rennzubehör-Bastelbude hatte offenbar schon in der Entwicklungsphase mit EMV-Problemen dieser Datenübertragung zu kämpfen, die wurden vermutlich ohne jemals einen echten Gokart zu konsultieren, durch Einfügen kleiner Drosseln in die Datenleitung abgestellt. Natürlich waren auch Drosseln in der Versorgung und in der Masseleitung! Entfernen letzterer hat die bestimmungsgemäße Funktion einigermaßen hergestellt.

Bloß so ein Gedanke ...
Warum haben die Vollpfosten nicht den Zündfunken als Trigger zum Starten der Datenpakete genutzt? Die maximale Taktfrequenz ist in der Klasse bei 300 Hz, im Leerlauf deutlich über 20 Hz. Damit hätte man der Übertragung problemlos einen Intervall zuteilen können in dem niemand dazwischenfunkt!
Wenn der Zähler überläuft, ist mit Motor-Stillstand zu rechnen, das Kriterium kann als Reserve-Interrupt verwendet werden.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 19:09
von ch_ris
ach so, Alex.
ich hab ca 3ms signal abstand wegen wer weis geh ich von 1ner aus. dann muss ich einen analogen schalter pollen. dann wird eine aktion, max255 ms ausgelöst. rpm während dessen egal. innerhalb des folgenden delay 1000ms werden zuvor erzeugte structs ins eeprom geschrieben.
ich weis nicht ob mir ne quasi permanente rpm berechnung zu viel zeit klaut?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 1. Jul 2022, 20:07
von Alexander470815
So habe ich das gemacht um eine Lüfterdrehzahl zu ermitteln:

Code: Alles auswählen

ISR(INT0_vect)								// Der Hardware interrupt der ausgelöst wird wenn ein Impuls kommt
{
	AddToFloatAvg(&Dreh,(15000000.0/(TCNT0+256.0*overflow)));	// Drehzahlwert dem Floating Average hinzufügen
	TCNT0=0;							// Timer wieder null setzen
	overflow=0;							// Überlauf wieder null setzen
}

ISR(TIMER0_OVF_vect)							// Interrupt der ausgelöst wird wenn der Timer überläuft(der hat nur 8bit also passiert das recht schnell)
{
	if(overflow<255)
		overflow++;						// Überläufe addieren, wenn 255 mal übergelaufen dann Drehzahl von null in den Floating Average schreiben
	else
		AddToFloatAvg(&Dreh,0);
}
An anderer Stelle kann man dann einfach den Mittelwert mit dem entsprechenden Makro abrufen.
Den Prescaler habe ich hier auf clk/64 gestellt was damit 16MHz/64=250kHz
250k * 60 = 15.000.000

Damit kommen da am Ende direkt U/min raus.
Die langsamst messbare Drehzahl wäre in dem Fall 15M/(255+255*256)=228 U/min
Könnte man aber einfach aufbohren indem man overflow größer werden lässt.

Ein Zählwert von 1500 wären 10.000 U/min
Ein Zählwert von 1501 wären 9.993 U/min
Bei 10.000 U/min hätte man somit noch eine Auflösung von 7 U/min.

Reicht das nicht könnte man den Prescaler ja noch schneller wählen.

Ich weiß ja nicht was das ganze am Ende machen soll, Drehzahlbegrenzer am Moped?