Go Down

Topic: Simulateur de roue dentée (EDIS4 36-1) #sinusoïde (Read 2719 times) previous topic - next topic

n2c_coxiste

Feb 14, 2016, 03:51 pm Last Edit: Feb 14, 2016, 05:38 pm by n2c_coxiste
Bonjour,à tous,
débutant dans ce vaste monde de l'Arduino, j'ai besoin de vos lumières...

je voudrais sortir un signal PWM, une sinusoïde qui se répète 34 fois, puis un signal "tordu" sur deux périodes, puis ça reprend en boucle.

Le but est de simuler le signal d'un capteur inductif placé devant une roue dentée, 36 dents mois une.

Je me base sur un programme tout fait qui génère une sinusoïde à fréquence variable fonction de l'entrée A0,

Le PWM pioche dans une table de 256 points,
Je pensais modifier le code pour intégrer une boucle,
- générer 34 fois une sinusoîde normale
- générer la dent manquante (2 périodes)

Mais je bute sur la compréhension de ceci:

Code: [Select]
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {

  sbi(PORTD,7);          // Test / set PORTD,7 high to observe timing with a oscope

  phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
  icnt=phaccu >> 24;     // use upper 8 bits for phase accu as frequency information
                         // read value fron ROM sine table and send to PWM DAC
  OCR2A=pgm_read_byte_near(sine9216 + icnt);   

  if(icnt1++ == 125) {  // increment variable c4ms all 4 milliseconds
    c4ms++;
    icnt1=0;
   }   

 cbi(PORTD,7);            // reset PORTD,7


La double période a cette forme:
Code: [Select]
// table of 512 "missing tooth" values on EDIS Trigger Wheel / two sine periods / stored in flash memory
PROGMEM const unsigned char dent512[] = {
 254, 254, 254, 254, 253, 253, 253, 252, 252, 251, 250, 249, 249, 248, 247, 245, 244, 243, 242, 240, 239, 238, 236, 234, 233, 231, 229, 227, 225, 223, 221, 219, 217, 215, 212, 210, 208, 205, 203, 200,
 198, 195, 192, 190, 187, 184, 181, 178, 176, 173, 170, 167, 164, 161, 158, 155, 152, 149, 146, 143, 139, 136, 133, 130, 127, 124, 121, 118, 115, 111, 108, 105, 102, 99, 96, 93, 90, 87, 84, 81, 78, 76,
 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3,
 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 46, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
 85, 85, 86, 86, 87, 87, 88, 88, 89, 89, 89, 90, 90, 91, 92, 93, 94, 94, 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 100, 101, 101, 101, 101, 102, 102, 102, 102, 103, 103, 103, 103, 103,
 104, 104, 104, 104, 105, 105, 105, 105, 106, 106, 106, 107, 107, 108, 108, 108, 109, 109, 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 112, 112, 113, 113, 113, 114, 114, 114, 114, 115, 115, 115,
 116, 116, 116, 116, 116, 117, 117, 117, 118, 118, 118, 119, 119, 119, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 122, 122, 122, 122, 122,
 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 126, 126, 126, 126, 126, 127, 127, 127, 127, 128, 128, 128, 128, 129, 129,
 129, 129, 129, 129, 129, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 132, 132, 132, 132, 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 135, 135, 135, 136, 136, 136, 136, 137, 137, 137, 137,
 138, 138, 138, 138, 139, 139, 139, 139, 140, 140, 141, 141, 141, 142, 142, 142, 143, 143, 144, 144, 145, 145, 145, 146, 146, 146, 147, 147, 148, 148, 148, 149, 149, 150, 150, 151, 151, 152, 152, 153,
 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 178, 179, 180, 181, 182, 183, 184, 186, 188, 190, 192, 195, 198, 200, 203, 205,
 208, 210, 212, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 234, 236, 238, 239, 240, 242, 243, 244, 245, 247, 248, 249, 249, 250, 251, 252, 252, 253, 253, 253, 254, 254, 254[/quote]

La sinusoIde celle ci:
[quote]// table of 256 sine values / one sine period / stored in flash memory
PROGMEM  const unsigned char sine256[]  = {
  127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
  242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
  221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
  76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
  33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124


Pour les avertis ça doit sembler bête et accessible, mais je sèche...
Pourquoi se sert-il des 8 bits supérieurs de phaccu (>>24) pour icnt???

Si quelqu'un y voit clair dans ce code...
Merci par avance,
Greg.




La sortie de l'Arduino sera dotée d'un filtre passe-bas


La plage de fréquence souhaitée:
300Hz<freq<8000Hz

Source de tout ceci:
http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-dds-sinewave-generator/


fdufnews

La période du signal est codée sur 256 octets. Les bits de plus faibles poids sont des décimales de l'angle. Ces décimales ne sont utilisées que pour le calcul de l'angle (afin d'avoir la précision nécessaire). Ces juste une convention.

n2c_coxiste

Oui, le 'hacheur' génère des créneaux 'PWM', le rapport cyclique dépend de chaque valeur de la table sin256...
Là ou bloque, c'est comment lui faire lire non pas les 256 valeurs de la table d'origine, mais 512 par exemple (deux périodes)

Je sais pas si c'est clair...

Ou luis faire lire une table de 36 périodes (34 identiques et deux patatoïdes)...

Greg.


n2c_coxiste

Code: [Select]

icnt=phaccu >> 24;     
OCR2A=pgm_read_byte_near(sine9216 + icnt);


icnt permet de pointer chaque valeur dans la table sine256
icnt est tiré ou extrait des 8 bits supérieurs du long word phaccu (icnt=phaccu >> 24;

j'ai tenté de manipuler icnt=phaccu >> 24; pour avoir une plus grande plage pour icnt, en vain...

fdufnews

#4
Feb 14, 2016, 06:15 pm Last Edit: Feb 14, 2016, 06:16 pm by fdufnews
Pour avoir une période codée sur 512 pas au lieu de 256, il faut modifier le code:
il faut définir icnt comme un int au lieu d'un byte
icnt=phaccu >> 24; doir être remplacé par icnt=phaccu >> 23;
mais attention, le calcul sur un entier au lieu d'un octet va allonger la durée du traitement de l'interruption.

Si tu veux faire générer n fois une table et m fois une autre table, il faut compter le nombre de tours de l'accumulateur. Pour certaines valeurs de ce compteur il faut utiliser une table à la place de l'autre. Cela revient à changer le nom de la table dans cette ligne:
OCR2A=pgm_read_byte_near(sine9216 + icnt);

n2c_coxiste

icnt est déclaré en byte,
je change en int
puis
icnt=phaccu >> 16;
ça enlève la limitation à 256?
bon, aspirine.

fdufnews

phaccu est un long (32 bits). Si tu fais >>16 alors icnt sera sur 16 bits et il faudra que tu gères une table de 16 bits (65536 octets).

fdufnews

Définir une longue table n'a de sens que si tu veux une grande précision dans la reconstruction de ton signal.

n2c_coxiste

OCR2A=pgm_read_byte_near(sine9216 + icnt);
oui, là c'est pas une méthode fine.... j'avoue... Grosse table de 9116 valeurs, 34 répétitions de la même sinusoïde... mais ça ne prend que 40% de l'espace et ça évitait de boucler dans le programme...

il y a sans doute plus fin!
Greg.


ha oui, donc sur 9 bits on a 512, ce qui permet de lire 17 fois une double sinus et une fois le signal patatoïde qui dure deux périodes...

n2c_coxiste

Bon, je ne peux pas visualiser pour le moment, ça compile, mais je n'ai pas de quoi réaliser le filtre passe-bas à la maison...

Code: [Select]
/*
 * DDS Sine Generator mit ATMEGS 168
 * Timer2 generates the  31250 KHz Clock Interrupt
 *
 * KHM 2009 /  Martin Nawrath
 * Kunsthochschule fuer Medien Koeln
 * Academy of Media Arts Cologne

 */

#include "avr/pgmspace.h"

// table of 512 double sine values / 17x double sine period  / stored in flash memory
PROGMEM  const unsigned char sinus512[]  = {
254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,
176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,
23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,
81,84,87,90,93,96,99,102,105,108,111,115,118,121,124,127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,
223,225,227,229,231,233,234,236,238,239,240,242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,
240,239,238,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,
118,115,111,108,105,102,99,96,93,90,87,84,81,78,76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,
3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124,127,130,133,136,139,143,146,
149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,242,243,244,245,247,248,249,249,250,
251,252,252,253,253,253,254,254,254
};

// table of 512 dent manquante values / 1x cette double period / stored in flash memory
PROGMEM  const unsigned char patate512[]  = {
254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,
176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,
23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,33,35,37,39,42,44,46,49,51,53,55,57,59,61,63,65,67,69,71,
72,73,74,75,76,77,78,79,80,81,82,83,84,85,85,86,86,87,87,88,88,89,89,89,90,90,91,92,93,94,94,94,94,95,95,96,96,97,97,98,98,99,99,100,100,100,101,101,101,101,102,102,102,102,103,103,103,103,
103,104,104,104,104,105,105,105,105,106,106,106,107,107,108,108,108,109,109,109,109,110,110,110,111,111,111,112,112,112,112,113,113,113,114,114,114,114,115,115,115,116,116,116,116,116,117,117,
117,118,118,118,119,119,119,120,120,120,120,120,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,122,122,122,122,122,122,122,122,122,122,122,123,123,123,123,123,123,123,124,124,
124,124,124,124,124,125,125,125,125,125,126,126,126,126,126,127,127,127,127,128,128,128,128,129,129,129,129,129,129,129,130,130,130,130,131,131,131,131,131,131,132,132,132,132,133,133,133,133,
133,134,134,134,134,134,135,135,135,136,136,136,136,137,137,137,137,138,138,138,138,139,139,139,139,140,140,141,141,141,142,142,142,143,143,144,144,145,145,145,146,146,146,147,147,148,148,148,
149,149,150,150,151,151,152,152,153,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,178,179,180,181,182,183,184,186,188,190,192,195,198,200,203,
205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254
};

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

int ledPin = 13;                 // LED pin 7
int testPin = 7;
int t2Pin = 6;
byte bb;

double dfreq;
// const double refclk=31372.549;  // =16MHz / 510
const double refclk=31376.6;      // measured

// variables used inside interrupt service declared as voilatile
volatile int icnt;              // var inside interrupt
volatile int dcnt;              // var nb lecture table sinus512
volatile byte icnt1;             // var inside interrupt
volatile byte c4ms;              // counter incremented all 4ms
volatile unsigned long phaccu;   // phase accumulator
volatile unsigned long tword_m;  // dds tuning word m

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  Serial.begin(115200);        // connect to the serial port
  Serial.println("DDS Test");

  pinMode(6, OUTPUT);      // sets the digital pin as output
  pinMode(7, OUTPUT);      // sets the digital pin as output
  pinMode(11, OUTPUT);     // pin11= PWM  output / frequency output

  Setup_timer2();

  // disable interrupts to avoid timing distortion
  cbi (TIMSK0,TOIE0);              // disable Timer0 !!! delay() is now not available
  sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt

  dfreq=1000.0;                    // initial output frequency = 1000.o Hz
  tword_m=pow(2,32)*dfreq/refclk;  // calulate DDS new tuning word
  dcnt = 0;
}
void loop()
{
  while(1) {
     if (c4ms > 250) {                 // timer / chaque demie seconde vient lire A0
      c4ms=0;
      dfreq=analogRead(0);             // read Poti on analog pin 0 to adjust output frequency from 0..1023 Hz

      cbi (TIMSK2,TOIE2);              // disble Timer2 Interrupt
      tword_m=pow(2,32)*dfreq/refclk;  // calulate DDS new tuning word  http://www.analog.com/library/analogdialogue/archives/38-08/dds.html
      sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt

      /*Serial.print("dfreq= ");
      Serial.print(dfreq);
      Serial.print("tword_m= ");
      Serial.println(tword_m);
      Serial.print("icnt= ");
      Serial.println(icnt);
      Serial.print("isnt1= ");
      Serial.println(icnt1);
      Serial.print("phaccu= ");
      Serial.println(phaccu);
      //Serial.print("         ");*/
    }

   sbi(PORTD,6); // Test / set PORTD,6 high to observe timing with a scope
   cbi(PORTD,6); // Test /reset PORTD,6 high to observe timing with a scope
  }
 }
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock
void Setup_timer2() {

// Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);

// Timer2 PWM Mode set to Phase Correct PWM
  cbi (TCCR2A, COM2A0);  // clear Compare Match
  sbi (TCCR2A, COM2A1);

  sbi (TCCR2A, WGM20);  // Mode 1  / Phase Correct PWM
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);
}

//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)  ou M=binary tuning word
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {    //http://www.locoduino.org/spip.php?article88 qui explique l'interruption du timer2, ici toutes les 32µS cette boucle intervient

  sbi(PORTD,7);          // Test / set PORTD,7 high to observe timing with a oscope

  phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
  icnt=phaccu >> 23;     // use upper 9 bits for phase accu as frequency information
                         // read value fron ROM sine table and send to PWM DAC
  if(dcnt>=17){
        OCR2A=pgm_read_byte_near(sinus512 + icnt);    
              }
  else
              {
        OCR2A=pgm_read_byte_near(patate512 + icnt);
        dcnt = 0;
              }
  
  if(icnt1++ == 125) {  // increment variable c4ms all 4 milliseconds
    c4ms++;
    icnt1=0;
   }  

 cbi(PORTD,7);            // reset PORTD,7
    
    }


J'ai ajouté dcnt en compteur et un test if

fdufnews

Oui mais tu n'incrémentes jamais dcnt.
Tu le mets à zéro à 2 endroits.
Je crois que ton if sur dcnt est à l'envers.

n2c_coxiste

j'ai honte.............

Code: [Select]
if(dcnt<=17){
        OCR2A=pgm_read_byte_near(sinus512 + icnt);   
        dcnt = dcnt+1;
        }
  else
              {
        OCR2A=pgm_read_byte_near(patate512 + icnt);
        dcnt = 0;
              }
 
  if(icnt1++ == 125) {  // increment variable c4ms all 4 milliseconds
    c4ms++;
    icnt1=0;
   }   

BrUnO14200

Projet aquaponique  :https://forum.arduino.cc/index.php?topic=677286.msg4584918#new


dfgh

hello
notre ami super-Cinci a planché sur un tel simulateur.

Go Up