Show Posts
Pages: [1] 2 3 ... 5
1  International / Français / Re: alimenter arduino avec 5 volts externe ? on: July 27, 2014, 12:34:08 am
Bonjour,

le fil correspondant au signal du servo ne nécessite pas de courant important.
Dans ton montage, il que le + et le - de tes servos arrivent directement de ta source d'alimentation (et ne passe pas par l'ARDUINO)
2  International / Français / Re: gestion servo suivant temperature on: July 27, 2014, 12:23:47 am
Bonjour,

Tu devrais essayer d'initaliser la valeur de "pos" dans le setup :

Code:
    myservo.attach(9, 2000, 2000);  // attaches the servo on pin 9 to the servo object
    pos = 90;
    myservo.write(pos);                  // met le servo a la position de val
    delay(500);                           // attente de positionnement du servo
}

Sinon, quelles sont les valeurs affichées "tempok" et "consigne"...

3  International / Français / Timer : calcul du prescaler on: July 26, 2014, 09:56:34 am
Hello,

J'ai un doute sur la programmation d'un timer qui me donne des résultats qui ne correspondent pas au calcul

Sur un Aruino Nano V3.0, voilà le programme :

Code:
// Faire clignoter la led en utilisant une interrruption Timer2

// Calcul prescaler :
// Fréquence horloge / prescaler / fréquence souhaitée = OCRnA
// 16000000 / 1024 / 100 = 156.25

#define ledPin 13

void setup(){
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  // initialize timer1
  noInterrupts(); // disable all interrupts
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2 = 0;
  //compare match register 16MHz/256/2Hz
  OCR2A = 156;  // 256 maxi pour timer 2 (8bits)
  TCCR2B |= (1 << WGM21); // CTC mode
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); // 1024 prescaler
  TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt
  interrupts(); // enable all interrupts
  Serial.println("OK");
}

//timer compare interrupt service routine
// toggle LED pin
ISR(TIMER2_COMPA_vect){
  static int nbre = 0;
  nbre++;
  if (nbre > 100){
    digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
    nbre = 0;
  }
}

void loop(){
  static boolean lastLed;
  boolean valLed = digitalRead(ledPin);
  if (valLed){
    if (lastLed){
      Serial.println(millis());
      lastLed = false;
    }
  }
  else{
    lastLed = true;
  }
}

Et voilà le résultat :

Code:
1647
4957
8266
11576
14885
18195
21505
24814
28124

soit un interval de 3,31s.
si je reprends le calcul du prescaler et le traitement de l'affichage, je devrais avoir 2s!...
Alors je me suis certainement mélangé les pinceaux sur les registres de l'ARDUINO mais je ne sais pas où, si quelqu'un a vu ma boulette...
4  International / Français / Fonction RC_Reader() appelée par une interruption on: July 23, 2014, 01:12:52 pm
Bonsoir,

Dans la lecture des voies d'un récepteur, je souhaite remplacer l'appel de la procédure RC_Reader() qui était faite dans la fonction loop() par une interruption.
Ceci est motivé par des boucles de traitement un peu longues dans le programme final et un besoin d'avoir des valeurs fraiches.

Dans le programme tel que vous l'avez ci-dessous, la procédure RC_Reader() n'est appelée qu'une seule fois puis plus rien!

Code:
/*

http://playground.arduino.cc/Code/ReadReceiver

Copyright 2011 Lex Talionis (Lex.V.Talionis at gmail)
This program is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any
later version.

This code uses pin change interrupts and timer 1 to mesure the
time between the rise and fall of 3 channels of PPM
(Though often called PWM, see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1253149521/all)
on a typical RC car reciver.  It could be extended to as
many channels as you like.  It uses the PinChangeInt library
to notice when the signal pin goes high and low, and the
Timer1 library to record the time between.

*/
#include <PinChangeInt.h>    // http://playground.arduino.cc/Main/PinChangeInt
#include <PinChangeIntConfig.h>
#include <TimerOne.h>        // http://playground.arduino.cc/Code/Timer1

#include <MsTimer2.h> // inclusion de la librairie Timer2

//#define NO_PORTB_PINCHANGES //PinChangeInt setup
//#define NO_PORTC_PINCHANGES    //only port D pinchanges (see: http://playground.arduino.cc/Learning/Pins)
#define PIN_COUNT 4    //number of channels attached to the reciver
#define MAX_PIN_CHANGE_PINS PIN_COUNT

//arduino pins attached to the reciver
#define RC_Voie1 3   
#define RC_Voie2 5   
#define RC_Voie3 6
#define RC_Voie4 7
byte pin[] = {RC_Voie1, RC_Voie2, RC_Voie3, RC_Voie4};    //for maximum efficency thise pins should be attached
unsigned int time[] = {0,0,0,0};                // to the reciver's channels in the order listed here

byte state=0;
byte burp=0;    // a counter to see how many times the int has executed
byte cmd=0;     // a place to put our serial data
byte iRC=0;       // global counter for tracking what pin we are on


void flash() {
  static boolean output = HIGH;

  digitalWrite(13, output);
  output = !output;
}

void setup() {
    Serial.begin(9600);
    Serial.print("PinChangeInt ReciverReading test : ");

    Timer1.initialize(2200);    //longest pulse in PPM is usally 2.1 milliseconds,
                                //pick a period that gives you a little headroom.
    Timer1.stop();                //stop the counter
    Timer1.restart();            //set the clock to zero

    for (byte i=0; i<4; i++)
    {
        pinMode(pin[i], INPUT);     //set the pin to input
        digitalWrite(pin[i], HIGH); //use the internal pullup resistor
    }
    //PCintPort::attachInterrupt(pin[iRC], rise,RISING); // attach a PinChange Interrupt to our first pin
    PCintPort::attachInterrupt(RC_Voie1, rise,RISING); // attach a PinChange Interrupt to our first pin

// initialisation interruption Timer 2
//  MsTimer2::set(500, flash); // ça fonctionne la led clignotte
  MsTimer2::set(500, RC_Reader); // ne fonctionne pas
  MsTimer2::start(); // active Timer 2

}

void loop() {
    cmd=Serial.read();        //while you got some time gimme a systems report
    if (cmd=='p')
    {
        Serial.print("time:\t");
        for (byte i=0; i<PIN_COUNT;i++)
        {
            Serial.print(i,DEC);
            Serial.print(":");
            Serial.print(time[i],DEC);
            Serial.print("\t");
        }
        Serial.print(burp, DEC);
        Serial.println();
    }
    cmd=0;
    Serial.println("."); // ça s'affiche
//    RC_Reader();  // Remplacé par un appel via une interruption
}



Code:
void RC_Reader(){
  Serial.println("|");
 
    switch (state)
    {
        case RISING: //we have just seen a rising edge
            PCintPort::detachInterrupt(pin[iRC]);
            PCintPort::attachInterrupt(pin[iRC], fall, FALLING); //attach the falling end
            state=255;
            break;
        case FALLING: //we just saw a falling edge
            PCintPort::detachInterrupt(pin[iRC]);
            iRC++;                //move to the next pin
            iRC = iRC % PIN_COUNT;  //i ranges from 0 to PIN_COUNT
            PCintPort::attachInterrupt(pin[iRC], rise,RISING);
            state=255;
            break;
        /*default:
            //do nothing
            break;*/
    }
    burp++;


void rise()        //on the rising edge of the currently intresting pin
{
    Timer1.restart();        //set our stopwatch to 0
    Timer1.start();            //and start it up
    state=RISING;
}

void fall()        //on the falling edge of the signal
{
    state=FALLING;
    time[iRC]=readTimer1();    // read the time since timer1 was restarted
//  time[i]=Timer1.read();    // The function below has been ported into the
                            // the latest TimerOne class, if you have the
                            // new Timer1 lib you can use this line instead
    Timer1.stop();
}

unsigned long readTimer1()        //returns the value of the timer in microseconds
{                                    //rember! phase and freq correct mode counts
                                    //up to ICR1 then down again
    unsigned int tmp=TCNT1;
    char scale=0;
    switch (Timer1.clockSelectBits)
    {
    case 1:// no prescalse
        scale=0;
        break;
    case 2:// x8 prescale
        scale=3;
        break;
    case 3:// x64
        scale=6;
        break;
    case 4:// x256
        scale=8;
        break;
    case 5:// x1024
        scale=10;
        break;
    }
    while (TCNT1==tmp) //if the timer has not ticked yet
    {
        //do nothing -- max delay here is ~1023 cycles
    }
    tmp = (  (TCNT1>tmp) ? (tmp) : (ICR1-TCNT1)+ICR1  );//if we are counting down add the top value
                                                        //to how far we have counted down
    return ((tmp*1000L)/(F_CPU /1000L))<<scale;
}


Toutes vos remarques sont les biens venues...
5  International / Français / Re: Problème de classe et d'interruption : comment mixer les 2 on: July 21, 2014, 02:46:30 pm
Pour ceux que cela intéresse, voilà une partie de la solution trouvée dans un cours sur le net (ce n'est certainement pas le seul) :
http://www.bruno-garcia.net/www/Cours/cyclevie.html

Code:
//  recepteur currentRx[NBRE_IND_TAB](wptr);  // Données issues du récepteur
 
  recepteur  *currentRx[NBRE_IND_TAB];
  for (int i=0; i<NBRE_IND_TAB;i++) currentRx[i]=new recepteur(ptrDataRC);

Il faut modifier les accès aux données du tableau :
Code:
    (*currentRx[indTab++]).lire(type);  // Lecture Rx...

Je n'ai pas eu le temps de tester, d'autres traitements sont à mettre en oeuvre avant les premiers tests...

A+
Olivier
6  International / Français / Re: Problème de classe et d'interruption : comment mixer les 2 on: July 21, 2014, 12:24:28 pm
Il fallait s'en douter, je tombe sur un problème.

J'ai une classe :
Code:
class recepteur {
public:
  unsigned long voie1;
  unsigned long voie2;
  unsigned long voie3;
  unsigned long voie4;

  int* ptrDataRC;

  recepteur(int*);
};

Dont voici le constructeur
Code:
recepteur::recepteur(int* wDataRC){
  voie1 = 1500;
  voie2 = 1500;
  voie3 = 1500;
  voie4 = 1500;
  ptrDataRC = wDataRC;
}

Ma question : comment déclarer un tableau de récepteur.
Tout les essais ne compilent pas :
Code:
  recepteur tabRx[NBRE_IND_TAB];  //  error: no matching function for call to 'recepteur::recepteur()'
  recepteur tabRx[NBRE_IND_TAB](NULL);  //  bad array initializer - invalid conversion from 'int' to 'int*'
  recepteur tabRx[NBRE_IND_TAB]((int*) NULL);  //  bad array initializer - invalid conversion from 'int' to 'int*'
  // Même en faisant référence
  int* wPtr = NULL;   // ou autre valeur
  recepteur tabRx[NBRE_IND_TAB](wPtr);  // bad array initializer - invalid conversion from 'int' to 'int*'

Si quelqu'un a la solution....
7  International / Français / Re: Problème de classe et d'interruption : comment mixer les 2 on: July 21, 2014, 11:43:56 am
Bonsoir,

J'ai toujours un peu de mal à "déchiffrer" des librairies mais je vais regarder avec attention.

J'ai néanmoins trouvé une idée cette nuit que je vais essayé de mettre en oeuvre. L'idée est d'ajouter une propriété cette classe qui correspond à l'adresse des variables globales dont on a besoin dans la classe.

Affaire à suivre...
8  International / Français / Problème de classe et d'interruption : comment mixer les 2 on: July 20, 2014, 12:39:30 pm
Bonsoir à tous,

Je me faisais une joie d'utiliser les classes afin de programmer proprement, mais je tombe dans une impasse.
Sachant que :
Le code contenu dans une classe ne voit que les propriétés et méthodes de cette classe.
Il n'est pas possible d'attacher une interruption dans une méthode d'une classe (message = multiple definition of 'PCintPort::PCint()').
La seule possibilité de transmettre des données aux méthodes d'une classe est via les paramètres de ces méthodes.

Comment faire lorsqu'on doit récupérer plusieurs fois (boucle jusqu'à ce que cela soit bon) des données qui ne peuvent être lues que par interruption


Cas concret :
Un récepteur (modèle réduit) donne les positions de 4 voies.
Pour que le programme connaisse la fonction de chaque voie, une méthode demande à l'utilisateur de poisitionner les manches de la radio dans des configurations particulières (tout au neutre, puis pas au max, puis pas au mini, puis....)
Le programme détermine que l'utilisateur a positionner les manches dans la position demandée lorsque les données seront dites 'stables'

J'ai donc développer une méthode 'calibrer' qui me renvoit dans l'intance 'récepteur' les valeurs demandées.


Code:
class recepteur {
public:
  unsigned long voie1;
  unsigned long voie2;
  unsigned long voie3;
  unsigned long voie4;

  recepteur();
  int calibrer(char);
};


int recepteur::calibrer(char type) {
  // Attendre que le Rx lu soit stable
  // Test : OK
  // --------------------------------------------------
  recepteur currentRx[NBRE_IND_TAB];  // Données issues du récepteur
  int nbreIter = 0; // Nbre d'itération pour avoir une valeur stable
  int indTab = 0;
  boolean stable = false;
  boolean minData = false;  // Il faut avoir rempli le tableau
  do{  // Attendre que les données soient stable
    currentRx[indTab++].lire(type);  // Lecture Rx...
    nbreIter++;
    if (indTab >= NBRE_IND_TAB) {
      indTab = 0;  //
      minData = true;  // Le tableau est complet
    }
    if (minData) {  // Le tableau est complet alors calcul de l'écart
      //recepteur minRx = recepteur(-1);
      recepteur minRx(-1);
      recepteur maxRx = recepteur(-1);
      // Détermine le min et le max pour chaque voie
      for (int i = 0; i < NBRE_IND_TAB; i++){
        minRx.minimum(currentRx[i]);
        maxRx.maximum(currentRx[i]);
      }
      stable = maxRx.stable(minRx);  // Ecart sur chaque voie < ERR
//      minRx.debug();
//      maxRx.debug();
    }
  }
  while (!stable || !minData);
 
  recepteur stableRx = recepteur(0);
  for (int i = 0; i < NBRE_IND_TAB; i++) stableRx += currentRx[i];
  stableRx /= NBRE_IND_TAB;
 
  voie1 = stableRx.voie1;
  voie2 = stableRx.voie2;
  voie3 = stableRx.voie3;
  voie4 = stableRx.voie4;
 
  return nbreIter;


void recepteur::lire(char type){
  // <TODO> A remplacer par la lecture du récepteur...
//  voie1 = random(900, 2100);
//  voie2 = random(900, 2100);
//  voie3 = random(900, 2100);
//  voie4 = random(900, 2100);

  voie1 = Donnée issue du traitement d'une interruption pin n (temps écoulé entre le front montant et le front descendant)
  voie2 = Donnée issue du traitement d'une it...
  voie3 = Donnée issue du traitement d'une it...
  voie4 = Donnée issue du traitement d'une it...
 
}



La lecture des voies RC se fait par du code du style :
Code:
#include <PinChangeInt.h>    // http://playground.arduino.cc/Main/PinChangeInt
#include <PinChangeIntConfig.h>
#include <TimerOne.h>        // http://playground.arduino.cc/Code/Timer1

#define NO_PORTB_PINCHANGES //PinChangeInt setup
#define NO_PORTC_PINCHANGES    //only port D pinchanges (see: http://playground.arduino.cc/Learning/Pins)
#define PIN_COUNT 3    //number of channels attached to the reciver
#define MAX_PIN_CHANGE_PINS PIN_COUNT

#define RC_TURN 3    //arduino pins attached to the reciver
#define RC_FWD 2
#define RC_FIRE 4
byte pin[] = {RC_FWD, RC_TURN, RC_FIRE};    //for maximum efficency thise pins should be attached
unsigned int time[] = {0,0,0};                // to the reciver's channels in the order listed here

byte state=0;
byte burp=0;    // a counter to see how many times the int has executed
byte cmd=0;     // a place to put our serial data
byte i=0;       // global counter for tracking what pin we are on

void setup() {
    Serial.begin(115200);
    Serial.print("PinChangeInt ReciverReading test");
    Serial.println();            //warm up the serial port

    Timer1.initialize(2200);    //longest pulse in PPM is usally 2.1 milliseconds,
                                //pick a period that gives you a little headroom.
    Timer1.stop();                //stop the counter
    Timer1.restart();            //set the clock to zero

    for (byte i=0; i<3; i++)
    {
        pinMode(pin[i], INPUT);     //set the pin to input
        digitalWrite(pin[i], HIGH); //use the internal pullup resistor
    }
    PCintPort::attachInterrupt(pin[i], rise,RISING); // attach a PinChange Interrupt to our first pin
}

void loop() {
    cmd=Serial.read();        //while you got some time gimme a systems report
    if (cmd=='p')
    {
        Serial.print("time:\t");
        for (byte i=0; i<PIN_COUNT;i++)
        {
            Serial.print(i,DEC);
            Serial.print(":");
            Serial.print(time[i],DEC);
            Serial.print("\t");
        }
        Serial.print(burp, DEC);
        Serial.println();
    }
    cmd=0;
    switch (state)
    {
        case RISING: //we have just seen a rising edge
            PCintPort::detachInterrupt(pin[i]);
            PCintPort::attachInterrupt(pin[i], fall, FALLING); //attach the falling end
            state=255;
            break;
        case FALLING: //we just saw a falling edge
            PCintPort::detachInterrupt(pin[i]);
            i++;                //move to the next pin
            i = i % PIN_COUNT;  //i ranges from 0 to PIN_COUNT
            PCintPort::attachInterrupt(pin[i], rise,RISING);
            state=255;
            break;
        /*default:
            //do nothing
            break;*/
    }
}

void rise()        //on the rising edge of the currently intresting pin
{
    Timer1.restart();        //set our stopwatch to 0
    Timer1.start();            //and start it up
    state=RISING;
//  Serial.print('r');
    burp++;
}

void fall()        //on the falling edge of the signal
{
    state=FALLING;
    time[i]=readTimer1();    // read the time since timer1 was restarted
//  time[i]=Timer1.read();    // The function below has been ported into the
                            // the latest TimerOne class, if you have the
                            // new Timer1 lib you can use this line instead
    Timer1.stop();
//  Serial.print('f');
}

unsigned long readTimer1()        //returns the value of the timer in microseconds
{                                    //rember! phase and freq correct mode counts
                                    //up to ICR1 then down again
    unsigned int tmp=TCNT1;
    char scale=0;
    switch (Timer1.clockSelectBits)
    {
    case 1:// no prescalse
        scale=0;
        break;
    case 2:// x8 prescale
        scale=3;
        break;
    case 3:// x64
        scale=6;
        break;
    case 4:// x256
        scale=8;
        break;
    case 5:// x1024
        scale=10;
        break;
    }
    while (TCNT1==tmp) //if the timer has not ticked yet
    {
        //do nothing -- max delay here is ~1023 cycles
    }
    tmp = (  (TCNT1>tmp) ? (tmp) : (ICR1-TCNT1)+ICR1  );//if we are counting down add the top value
                                                        //to how far we have counted down
    return ((tmp*1000L)/(F_CPU /1000L))<<scale;
}

En bref, comment mixer les 2 programmes...

Merci pour vos lumières
9  International / Français / Re: Accès a des variables d'une classe on: July 20, 2014, 01:22:37 am
Bonjour,

La solution ne serait pas  :

Code:
int zzz;
zzz=myTeleInfo->ISOUSC;
// ou :
zzz=(*myTeleInfo).ISOUSC;

puisque tu déclare myTeleInfo comme un pointeur :

Code:
TeleInfo* myTeleInfo;

A tester...

A+
Olivier
10  International / Français / Re: GPS Adafruit - Erreur de positionnement on: December 24, 2013, 02:37:01 am
Pas de souci!

Je viens de trouver une explication dans la librairie TinyGPS : la méthode parse_degrees() fait le job. Il faut donc se taper la règle de trois! ça devrais être dans mes cordes smiley-wink

Joyeux Noël à tous
Olivier
11  International / Français / Re: GPS Adafruit - Erreur de positionnement on: December 23, 2013, 02:52:21 pm
Bien joué! Cela ne m'était pas venu à l'esprit.

Bon maintenant : comment convertir les degrés minutes secondes en degrés et centièmes de degrés.
J'ai cherché une commande interne au GPS pour spécifié que je voulais les information sous ce format : je n'ai pas trouvé.
J'ai cherché dans les méthodes de la librairie Adafruit : sans succès.
J'ai cherché dans la librairie TinyGPS (qui donne le bon résultat) une méthodes qui ferait la conversion : cela ne m'a pas sauté au yeux!

Vos idées sont les biens venues.
Olivier

12  International / Français / Re: GPS Adafruit - Erreur de positionnement on: December 23, 2013, 11:58:12 am

L'erreur représente 45km d'erreur à vol d'oiseau!!!!!!!!
Si tu trouves ça acceptable, sache que je ne voyagerai jamais avec toi, que cela soit à la place conducteur comme à la place du copilote!!!

Si tu penses que c'est acceptable, va faire un tour sur sur http://maps.google.fr, http://www.lexilogos.com/calcul_distances.htm et rentre les 2 coordonnées pour voir.

A+
Olivier

13  International / Français / [Résolu] GPS Adafruit - Erreur de positionnement on: December 23, 2013, 09:51:16 am
Bonjour,

Je reviens à la recherche d'explications concernant un problème de GPS (http://www.adafruit.com/products/746#Downloads) avec des données fausses :

Voici le bilan que j'ai pu établir jusqu'à présent :

Je me trouve ici : 46.995149 N  3.393490 E
Ces données sont prises sur https://maps.google.fr.

Voici les données renvoyées par le programme et la librairie Adafruit :
$GPGGA,092221.000,4659.7671,N,00323.6700,E,1,4,6.10,113.7,M,48.1,M,,*56
$GPRMC,092221.000,A,4659.7671,N,00323.6700,E,1.45,221.57,221213,,,A*6C
Location: 4659.7670N, 323.6700E
//09:22:21/046597672N003236699E011370
$PGTOP,11,2*6E

$PGTOP,11,2*6E
$GPGGA,092850.000,4659.7662,N,00323.6782,E,1,6,2.36,133.4,M,48.1,M,,*51
$GPRMC,092850.000,A,4659.7662,N,00323.6782,E,0.81,228.39,221213,,,A*60
$PGTOP,11,2*6E
$GPGGA,092851.000,4659.7627,N,00323.6756,E,1,7,1.61,134.2,M,48.1,M,,*59
$GPRMC,092851.000,A,4659.7627,N,00323.6756,E,1.10,208.34,221213,,,A*6F
$PGTOP,11,2*6E
$GPGGA,092852.000,4659.7579,N,00323.6719,E,1,7,1.61,135.1,M,48.1,M,,*5B
$GPRMC,092852.000,A,4659.7579,N,00323.6719,E,1.71,209.89,221213,,,A*6F

Time: 9:28:52.0
Date: 22/12/2013
Fix: 1 quality: 1
Location: 4659.7578N, 323.6719E
Speed (knots): 1.71
Angle: 209.89
Altitude: 133.40
Satellites: 6
$PGTOP,11,2*6E

Bref, il y a une grosse erreur!


Le GPS possède une mémoire flash que l'on peut exploiter. Voici ce que cela donne lorsque l'on pas ces données dans le parser Adafruit (http://learn.adafruit.com/custom/ultimate-gps-parser) :

Code:
<Count Data="6">
     <UTC>Sat Dec 21 2013 14:05:26 GMT+0100</UTC>
     <FixType>04</FixType>
     <Lat>46.995149</Lat>
     <Lon>3.393490</Lon>
     <HGT>249</HGT>
 </Count>

Les données sont correctes dans la méoire flash du GPS mais arrive avec une erreur lorsque ces données sont traitées par la librairie/ARDUINO!
 
 Mes questions :
  * Est-ce quelqu'un aurait déjà expérimenté ce GPS et cette librairie avec succès?
  * Avez-vous constater ce même phénomène?
  * Est-ce que quelqu'un l'a résolu et comment?
  * Est-ce qu'il existerait une version de la librairie (si c'est elle qui est en cause) qui corrigerait le problème (la version utilisée : https://github.com/adafruit/Adafruit-GPS-Library)
 
 A noter que j'ai fait un test avec la librairie TinyGPS qui fonctionne correctement.
 
 Vos réflexion sont les biens venues
 Olivier BERNARD
14  International / Français / Re: ServoTimer2.cpp:126: error: expected primary-expression before '?' on: December 16, 2013, 10:53:06 am
Bien vu!

J'ai quelques difficultés à télécharger la lib : il m'a mis tout un tas de '?'. Je pensais tous les avoir supprimés.

Merci de m'avoir ouvert les yeux!
Olivier
15  International / Français / ServoTimer2.cpp:126: error: expected primary-expression before '?' on: December 16, 2013, 10:09:53 am
Bonjour à tous,


Je suis entrain de tester la library servoTimer2 pour pouvoir commander des servos avec le timer2 (si le timer1 est déjà occupé!)
J'ai téléchargé la lib ici :
http://code.google.com/p/duinos/source/browse/trunk/libraries/ServoTimer2/
J'ai fais la modification pour être compatible avec la version 1.0.5 de l'IDE.

Mais la compil m'envoie le message suivant :

Code:
ServoTimer2.cpp: In function 'void writeChan(uint8_t, int)':
ServoTimer2.cpp:126: error: expected primary-expression before '?' token
ServoTimer2.cpp:126: error: expected `:' before ')' token
ServoTimer2.cpp:126: error: expected primary-expression before ')' token
ServoTimer2.cpp:127: error: expected primary-expression before '?' token
ServoTimer2.cpp:127: error: expected `:' before ';' token
ServoTimer2.cpp:127: error: expected primary-expression before ';' token
ServoTimer2.cpp:128: error: expected primary-expression before '?' token
ServoTimer2.cpp:128: error: expected `:' before ')' token
ServoTimer2.cpp:128: error: expected primary-expression before ')' token
ServoTimer2.cpp:129: error: expected primary-expression before '?' token
ServoTimer2.cpp:129: error: expected `:' before ';' token
ServoTimer2.cpp:129: error: expected primary-expression before ';' token

Voici les sources


ServoTimer2.h
Code:
// ensure this library description is only included once
#ifndef ServoTimer2_h
#define ServoTimer2_h

//#include <inttypes.h>
//#include <wiring.h>

#define MIN_PULSE_WIDTH?   750    // the shortest pulse sent to a servo  
#define MAX_PULSE_WIDTH?  2250    // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH  1000    // default pulse width when servo is attached
#define FRAME_SYNC_PERIOD   20000    // total frame duration in microseconds
#define NBR_CHANNELS 8   // the maximum number of channels, don't change this

typedef struct  {
uint8_t nbr    :
  5 ;  // a pin number from 0 to 31
uint8_t isActive   :
  1 ;  // false if this channel not enabled, pin only pulsed if true
}
ServoPin_t   ;  

typedef struct {
  ServoPin_t Pin;
  byte counter;
  byte remainder;
}  
servo_t;

class ServoTimer2
{
public:
  // constructor:
  ServoTimer2();

  uint8_t attach(int);     // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
  // the attached servo is pulsed with the current pulse width value, (see the write method)
  void detach();
  void write(int);     // store the pulse width in microseconds (between MIN_PULSE_WIDTH and MAX_PULSE_WIDTH)for this channel
  int read();    // returns current pulse width in microseconds for this servo
  boolean attached();  // return true if this servo is attached
private:
  uint8_t chanIndex;  // index into the channel data for this servo

};


// the following ServoArrayT2 class is not implimented in the first version of this library
class ServoArrayT2
{
public:
  // constructor:
  ServoArrayT2();

  uint8_t attach(int);     // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
  // channels are assigned consecutively starting from 1
  // the attached servo is pulsed with the current pulse width value, (see the write method)
  void detach(int);    // detach the servo on the given channel
  void write(int,int);     // store the pulse width in microseconds (between MIN_PULSE_WIDTH and MAX_PULSE_WIDTH)for the given channel
  int read(int);    // returns current pulse width in microseconds for the given channel
  boolean attached(int);   // return true if the servo on the given channel is attached
private:
  uint8_t chanIndex;  // index into the channel data for this servo

};

#endif



ServoTimer2.cpp
Code:
/*
  ServoTimer2.c - Interrupt driven Servo library for Arduino using Timer2- Version 0.1
 Copyright (c) 2008 Michael Margolis.  All right reserved.
  */

#if ARDUINO >= 100
#include "Arduino.h"
#else
extern "C" {
  // AVR LibC Includes
#include <inttypes.h>
#include <avr/interrupt.h>
#include "WProgram.h"
}
#endif

#include "ServoTimer2.h"
static void initISR();  
static void writeChan(uint8_t chan, int pulsewidth);

#define FRAME_SYNC_INDEX   0   // frame sync delay is the first entry in the channel array
//#define FRAME_SYNC_PERIOD  20000     // total frame duration in microseconds
#define FRAME_SYNC_DELAY   ((FRAME_SYNC_PERIOD - ( NBR_CHANNELS * DEFAULT_PULSE_WIDTH))/ 128) // number of iterations of the ISR to get the desired frame rate
#define DELAY_ADJUST   8   // number of microseconds of calculation overhead to be subtracted from pulse timings  

static servo_t servos[NBR_CHANNELS+1];    // static array holding servo data for all channels

static volatile uint8_t Channel;   // counter holding the channel being pulsed
static volatile uint8_t ISRCount;  // iteration counter used in the interrupt routines;
uint8_t ChannelCount = 0;      // counter holding the number of attached channels
static boolean isStarted = false;  // flag to indicate if the ISR has been initialised

ISR (TIMER2_OVF_vect)
{
  ++ISRCount; // increment the overlflow counter
  if (ISRCount ==  servos[Channel].counter ) // are we on the final iteration for this channel
  {
    TCNT2 =  servos[Channel].remainder;   // yes, set count for overflow after remainder ticks
  }  
  else if(ISRCount >  servos[Channel].counter)  
  {
    // we have finished timing the channel so pulse it low and move on
    if(servos[Channel].Pin.isActive == true)       // check if activated
      digitalWrite( servos[Channel].Pin.nbr,LOW); // pulse this channel low if active  

    Channel++;    // increment to the next channel
    ISRCount = 0; // reset the isr iteration counter
    TCNT2 = 0;    // reset the clock counter register
    if( (Channel != FRAME_SYNC_INDEX) && (Channel <= NBR_CHANNELS) ){       // check if we need to pulse this channel    
      if(servos[Channel].Pin.isActive == true)     // check if activated
        digitalWrite( servos[Channel].Pin.nbr,HIGH); // its an active channel so pulse it high  
    }
    else if(Channel > NBR_CHANNELS){
      Channel = 0; // all done so start over    
    }
  }  
}

ServoTimer2::ServoTimer2()
{
  if( ChannelCount < NBR_CHANNELS)  
    this->chanIndex = ++ChannelCount;  // assign a channel number to this instance
  else
    this->chanIndex = 0;  // todo?  // too many channels, assigning 0 inhibits this instance from functioning
}

uint8_t ServoTimer2::attach(int pin)
{
  if( isStarted == false)
    initISR();    
  if(this->chanIndex > 0)  
  {
    //debug("attaching chan = ", chanIndex);
    pinMode( pin, OUTPUT) ;  // set servo pin to output
    servos[this->chanIndex].Pin.nbr = pin;  
    servos[this->chanIndex].Pin.isActive = true;  
  }
  return this->chanIndex ;
}

void ServoTimer2::detach()  
{
  servos[this->chanIndex].Pin.isActive = false;  
}

void ServoTimer2::write(int pulsewidth)
{
  writeChan(this->chanIndex, pulsewidth); // call the static function to store the data for this servo?      
}

int ServoTimer2::read()
{
  unsigned int pulsewidth;
  if( this->chanIndex > 0)
    pulsewidth =  servos[this->chanIndex].counter * 128 + ((255 - servos[this->chanIndex].remainder) / 2) + DELAY_ADJUST ;
  else
    pulsewidth  = 0;
  return pulsewidth;  
}

boolean ServoTimer2::attached()
{
  return servos[this->chanIndex].Pin.isActive ;
}


static void writeChan(uint8_t chan, int pulsewidth)
{
  // calculate and store the values for the given channel
  if( (chan > 0) && (chan <= NBR_CHANNELS) )   // ensure channel is valid
  {
    if( pulsewidth < MIN_PULSE_WIDTH )    // ensure pulse width is valid
      pulsewidth = MIN_PULSE_WIDTH;
    else if( pulsewidth > MAX_PULSE_WIDTH )
      pulsewidth = MAX_PULSE_WIDTH;

    pulsewidth -=DELAY_ADJUST;                     // subtract the time it takes to process the start and end pulses (mostly from digitalWrite)
    servos[chan].counter = pulsewidth / 128;    
    servos[chan].remainder = 255 - (2 * (pulsewidth - ( servos[chan].counter * 128)));  // the number of 0.5us ticks for timer overflow      
  }
}


static void initISR()
{  
  for(uint8_t i=1; i <= NBR_CHANNELS; i++) {  // channels start from 1    
    writeChan(i, DEFAULT_PULSE_WIDTH);  // store default values?      
  }
  servos[FRAME_SYNC_INDEX].counter = FRAME_SYNC_DELAY;   // store the frame sync period

  Channel = 0;  // clear the channel index  
  ISRCount = 0;  // clear the value of the ISR counter;

  /* setup for timer 2 */
  TIMSK2 = 0;  // disable interrupts
  TCCR2A = 0;  // normal counting mode
  TCCR2B = _BV(CS21); // set prescaler of 8
  TCNT2 = 0;     // clear the timer2 count
  TIFR2 = _BV(TOV2);  // clear pending interrupts;
  TIMSK2 =  _BV(TOIE2) ; // enable the overflow interrupt?    

  isStarted = true;  // flag to indicate this initialisation code has been executed
}

Votre aide est la bien venue...
Olivier

Pages: [1] 2 3 ... 5