Go Down

Topic: Timer 2 15 khz frequenz mit variabler duty cycle (Read 5138 times) previous topic - next topic

Doc_Arduino

#30
Feb 10, 2016, 03:31 pm Last Edit: Feb 10, 2016, 03:33 pm by Doc_Arduino
Hallo,

ja, es gibt verschiedene Schreibweisen, haben alle ihre Vorteile, ist jedoch alles keine Hexerei, guck mal hier zum lesen:  http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ver.C3.A4ndern_von_Registerinhalten

ein Bsp.

Code: [Select]
/*
 Doc_Arduino - german Arduino Forum
 IDE 1.6.7
 Arduino Mega2560
 
*/

#ifndef sbi   // Bit setzen
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
#ifndef cbi  // Bit löschen
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif

byte Register_X;  


void setup()  {
  Serial.begin(9600);

  zeigeFormatiertesByte(Register_X);
  Register_X = (1<<7);                //setzt nur Bit 7
  zeigeFormatiertesByte(Register_X);
  Register_X = 128;                   //nochmal, nur dezimal
  zeigeFormatiertesByte(Register_X);
  Register_X = (1<<1);                //setzt nur Bit 1
  zeigeFormatiertesByte(Register_X);
  Register_X = (1<<3) | (1<<5);       //setzt Bit 3 und 5
  zeigeFormatiertesByte(Register_X);
  Serial.println();

  sbi(Register_X, 7);                 // setzt Bit 7 zusätzlich
  zeigeFormatiertesByte(Register_X);
  sbi(Register_X, 1);                 // setzt Bit 1 zusätzlich
  zeigeFormatiertesByte(Register_X);
  Serial.println();

  cbi(Register_X, 3);                 // löscht Bit 7 einzeln
  zeigeFormatiertesByte(Register_X);
  cbi(Register_X, 5);                 // löscht Bit 7 einzeln
  zeigeFormatiertesByte(Register_X);
}

  
void loop() {          
      
}   // loop Ende


// ****** Funktionen ******* //

void zeigeFormatiertesByte (byte &value)
{
  for (int i=7;i>=4;i--) Serial.print(bitRead(value,i));  // von jurs, formatiert Byte in Binärform
  Serial.print(".");
  for (int i=3;i>=0;i--) Serial.print(bitRead(value,i));  
  Serial.println();
}      



Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

Hallo,

nochwas. Die Namen der Bits in den Registern sind im Grunde genommen "auch nur" Bitnummern. Jedoch mit Klarnamen versehen. Es existiert irgendwo in der IDE bzw. im Compiler für jeden µC einen Art Übersetzungstabelle mit all seinen Registern usw. Vieles davon nimmt uns die Arduino IDE unsichtbar ab. Deswegen können wir unbekümmert die Namen der Register und der Bits mit ihren Namen verwenden, wie von Atmel im Datenblatt vorgesehen.

Code: [Select]
Register_X = (1<<FOC2A);                //setzt nur Bit 7
zeigeFormatiertesByte(Register_X);
Register_X = (1<<CS21);                 //setzt nur Bit 1
zeigeFormatiertesByte(Register_X);

Serial.println(FOC2A);
Serial.println(CS21);
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

murdok1980

Hab jetzt die Codes ausprobiert. Der mit dem einen Kanal und den 15,5 khz funktioniert nicht.
Die serielle Ausgabe sagt PWM per Poti ins value alles OK. Zwischen dem PIN11 und Masse messe ich 0Volt.
Zwischen PIN11 und Plus messe ich 5 Volt.
Hab den Code so hier angepasst. PIN6 und PIN7 sind für die Richtungsvorgabe der H-Brücke
Code: [Select]

/*
 Doc_Arduino - german Arduino Forum
 IDE 1.6.7
 Arduino Mega2560
 
 Timer 2: Fast-PWM, Mode 7
 TOP:  OCR2A     (Takt-Frequenz)
 Pulsweite: OCR2B  (<= TOP)
 Schaltpin:  9   (OC2B bzw. PH6) nicht invertiert
*/

#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))   // setzt das angegebene Bit auf 1
#endif

const byte _PWMpinB =  11;  // OC2B bzw. PH6 nicht invertiert, IRFxxxx Mosfet o.ä.
const byte _Poti = A0;     // Potentiometer
const byte OUTPUT_PIN2 = 6;
const byte OUTPUT_PIN3 = 7;

void setup()  {
  Serial.begin(9600);
  pinMode (OUTPUT_PIN2, OUTPUT);
  pinMode (OUTPUT_PIN3, OUTPUT);
  digitalWrite(OUTPUT_PIN2, LOW);
  digitalWrite(OUTPUT_PIN3, HIGH);
  pinMode(_PWMpinB, OUTPUT); 
  digitalWrite(_PWMpinB, LOW);    // OC2B
       
 
  set_Timer2();
}

 
void loop() {           
 
  int value = analogRead(_Poti)/8;  // <= TOP beachten !!!

  OCR2B = value;         // PWM x%  // <= TOP beachten !!!
 
  Serial.print(F("PWM Wert: ")); Serial.println(value);
  //delay(1000);
                     
}   // loop Ende


// ****** Funktionen ******* //
   
void set_Timer2()       // Fast-PWM, Mode 7
{
  cli();         // Interrupts ausschalten
  TCCR2A = 0;    // Reset TCCR1A Register
  TCCR2B = 0;    // Reset TCCR1B Register
  TIMSK2 = 0;    // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT2  = 0;    // Reset Start-Counter
  TCCR2A = (1<<COM2B1) | (1<<WGM21) | (1<<WGM20);  // non invert, set Mode 7
  TCCR2B = (1<<CS21) | (1<<WGM22);                 // Prescaler 8
  OCR2A = 128;   // TOP, zusammen mit Prescaler 8 >> 15,5kHz
  OCR2B = 0;     // Pulsweite, <= TOP
  sei();         // Interrupts einschalten
}  // end Funktion



Der erste Code mit 7,8 khz funktioniert, hab ihn so angepasst.
Code: [Select]

/*
 Doc_Arduino - german Arduino Forum
 IDE 1.6.7
 Arduino Mega2560
 
 Timer 2: Fast-PWM, Mode 3
 TOP:  0xFF     (Takt-Frequenz)
 Pulsweite: OCR2A  (<= TOP)
 Schaltpin: 10   (OC2A bzw. PB4) nicht invertiert
*/

#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))   // setzt das angegebene Bit auf 1
#endif

const byte _PWMpin = 11;   // OC2A bzw. PB4 nicht invertiert, IRFxxxx Mosfet o.ä.
const byte _Poti = A0;     // Potentiometer
const byte OUTPUT_PIN2 = 6;
const byte OUTPUT_PIN3 = 7;

void setup()  {
  Serial.begin(9600);
  pinMode (OUTPUT_PIN2, OUTPUT);
  pinMode (OUTPUT_PIN3, OUTPUT);
  digitalWrite(OUTPUT_PIN2, LOW);
  digitalWrite(OUTPUT_PIN3, HIGH);
  digitalWrite(_PWMpin, LOW);    // OC2A bzw. PB4 nicht invertiert
  pinMode(_PWMpin, OUTPUT);     
 
  set_Timer2();
 
}

 
void loop() {           
 
  int value = analogRead(_Poti)/4; 
 
  if (value == 0)  {
    digitalWrite(_PWMpin, LOW);   // PWM 0%
  }
  else  {
    sbi(TCCR2A, COM2A1);
    OCR2A = value;                // PWM x%
  }
 
  //Serial.print(F("PWM Wert: ")); Serial.println(value);
  //delay(1000);
 
                             
}   // loop Ende


// ****** Funktionen ******* //
   
void set_Timer2()       // Fast-PWM, Mode 3
{
  cli();         // Interrupts ausschalten
  TCCR2A = 0;    // Reset TCCR1A Register
  TCCR2B = 0;    // Reset TCCR1B Register
  TIMSK2 = 0;    // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT2  = 0;    // Reset Start-Counter
  TCCR2A = (1<<COM2A1) | (1<<WGM21) | (1<<WGM20);  // non invert, set Mode 3
  TCCR2B = (1<<CS21);                              // Prescaler 8 >> 7,8kHz
  OCR2A = 0;     // Pulsweite, < 255 (2^8)
  sei();         // Interrupts einschalten
}  // end Funktion



Grüße
Andre

Doc_Arduino

#33
Feb 10, 2016, 07:53 pm Last Edit: Feb 10, 2016, 08:04 pm by Doc_Arduino
Hallo,

statt erstmal Danke zu sagen wird gemosert. Und statt den Code und die Kommentare zu lesen wird wild probiert und gesagt, geht nicht. Das macht mich traurig.

Warum funktioniert wohl der 15kHz Code bei dir nicht?
Weil der nur auf Timer 2 Pin OC2B läuft. Nicht auf OC2A, wie die anderen.
Weil OC2A wegen dem TOP Wert OCR2A uns nicht zur Verfügung steht.
Schon mehrfach erwähnt das die Dinger hardware kodiert sind.
Habe nicht umsonst erwähnt das es beim Nano Pin 11 und 3 ist.

das hier hätte eigentlich auffallen müssen ... das was nicht paßt,

Quote
...
const byte _PWMpinB = 11;  // OC2B bzw. PH6 nicht invertiert
const byte _PWMpin   = 11;  // OC2A bzw. PB4 nicht invertiert
Lesen, sonst war alles umsonst.

Aber ich weis selbst, ist alles nicht so einfach ...  :)   Sorry wenn ich schimpfen mußte.

Du solltest auch die Namen usw. für deinen Nano anpassen. Nicht das du noch mehr durcheinander kommst.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

murdok1980

Hallo Doc
Das war so nicht gemeint, bin ja schon fleißig am lesen. Das PIN 3 und 11 zum Timer 2 gehören hab ich rausgelesen. Hab grade mal den PIN 11 auf 3 geändert und siehe da funzt. Schade das es auf PIN 11 nicht geht. Den PIN 3 brauch ich zwingend für das auslesen des Empfängers (Hardware Interrupt1).
Da wird mir wohl nix anderes übrig bleiben als mich in das Togglen eines PINs einzulesen, da gibts glaube ich etwas mit toggle bei compare oder so ähnlich , wobei das hier schon schwer genug ist. Hast du nen Tipp wo ich da was finde.
Danke für deine bisherige Hilfe.

Grüße
André

Serenifly

#35
Feb 10, 2016, 08:36 pm Last Edit: Feb 10, 2016, 08:47 pm by Serenifly
Oder nimm Timer1 und ICR. Wieso das Timer2 sein muss habe ich bisher noch nicht verstanden.

Das automatisch zu machen hat halt den Vorteil dass keine ISR ausgelöst wird. 15kHz sind 66µs. So schnell ständig den Code zu unterbrechen ist nicht so toll.

murdok1980

Hallo,
die Frage kann ich beantworten. Weil ich mit dem Timer 1 schon 2 mal PWM mit 15,5 khz erzeuge und aber noch einen 3. Kanal brauche.
Ich glaub langsam das wird bissl eng mit nem Nano.
Grüße
André

Serenifly

#37
Feb 10, 2016, 08:52 pm Last Edit: Feb 10, 2016, 08:53 pm by Serenifly
Ah. Das hatte ich übersehen.

Wegen des Interrupts. Du kannst statt einem Hardware Interrupt einen Pinchange Interrupt nehmen. Die sind komplizierter zu handhaben (da sich mehrere Pins einen Vektor teilen und man die Flanke per Hand abfragen muss), aber die gehen auf allen Pins (bis auf A6/A7 natürlich).

Oder man nimmt einfach eine fertige Library:
https://github.com/GreyGnome/EnableInterrupt

murdok1980

Die Enable InterruptLibrary sieht vielversprechend aus. Wenn sich da nix mit den Timern 0-2 ins Gehege kommt, könnte das funktionieren. Werd ich mal ausprobieren aber nicht mehr heute.
Vielleicht hat ja doc_arduino noch Idee mit dem Togglen von PINs.
Grüße
André

Serenifly

Die Beispiele da sind vielleicht etwas verwirrend. Du willst die Simple Version:
https://github.com/GreyGnome/EnableInterrupt/blob/master/examples/SimpleWithLibrary/SimpleWithLibrary.ino

Ist damit auch nicht anders als mit attachInterrupts()


Hier gibt es auch noch eine ältere Version die mit dem Atmega 328 und 2560 geht:
https://github.com/GreyGnome/PinChangeInt

Doc_Arduino

Hallo,

a) den Empfänger kannste nicht auf einen anderen Pin legen?
b) müssen es wirklich 15kHz sein, was hängt da eigentlich dran?
c) welche Pins sind denn von was belegt und welche sind noch frei?
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

murdok1980

Hallo,
2 und 3 lesen 2 Empfängerkanäle aus (Interrupt 0 und 1)
5,6,7,8 sind die Richtungsvorgaben für die 2 H-Brücken
9 und 10 sind die PWMs der 2 H-Brücken mit Timer 1.

Die 15 khz damit in dem Schiffsmodell die Motoren nicht pfeifen. Stört einfach in einem Scalmodell.
Das Schiff hat 3 Motoren deswegen die 3 H-Brücken. (Eine fehlt ja noch.
Zwei Analoge Eingänge brauche ich evtl. noch für die Strommessung der H-Brücken.
Der Rest ist frei.
Ich könnte ja auch nen Mega2560 nehmen aber ich hab den Platz im Modell nicht.
Grüße

André

Doc_Arduino

Hallo,

ich denke mal laut vor mich hin ...

Pin 2,3 sind gesetzt, bekommt man nicht frei

Nutzt du in deinem Code delay, millis oder micros? Wenn nicht, wäre Timer 0 frei und damit seine Pins, welche auf 5 und 6 rausgehen. Einen davon benötigten legste auf anderen freien um. Dann sollte man das von Timer 2 auf Timer 0 übertragen können.

Oder du mußt mittels I2C Bus einen Portexpander anschließen, womit du je nach Typ mindestens 8 digitale I/Os bekommst. 2 Pins sind von I2C belegt, bekommst dafür min. 6 zusätzlich. I2C wäre Hardwaremäßig Pin "A4", "A5". Oder softwaremäßig frei wählbar. Damit Pin 5 OC0B frei wird.

Mußte mal in Ruhe drüber nachdenken was so möglich ist.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

Oder wie gesagt Pin Change Interrupts. Die sind komplizierter zu handhaben, aber auf dem Atmega328 kann man da auf allen Pins (bis auf A6/A7 wenn vorhanden) Interrupts auslösen.

Doc_Arduino

Hallo,

ja, auch eine gute Idee. Wurde wohl "übersehen". Beim Pinout lesen hatte ich mich kurz mal gefragt, warum man nicht alle Pins als Interrupt nutzen kann, wenn an fast allen ein PCINTxx dran steht.

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Go Up