2016-06-07 2 views
0

Pour un projet contenant un contrôleur à bande LED, je souhaite remplacer la télécommande IR par un Arduino nano. Maintenant, après avoir fait quelques recherches (http://blog.allgaiershops.com/2012/05/10/reversing-an-rgb-led-remote/) et des mesures, j'ai trouvé que le contrôleur à bande LED utilise le protocole NEC.Programmation de minutage Arduino pour la sortie de signal NEC sur fil

Maintenant, j'ai essayé de créer un programme qui va émuler l'un des événements de presse de bouton tel que mesuré sur le IR_receiver. Cependant, lorsque la sortie sur la broche numérique 2 (qui est prise en charge par PWM) est mesurée, la synchronisation n'est pas proche de la valeur désirée. Cependant, si j'utilise la boucle for comme écrit dans les fonctions (sortie haut/bas) dans la boucle principale, il est possible de créer une sortie haute pour 500us. Je me demandais si vous pouviez me donner un peu de soutien pour que le code fonctionne, ou pourriez-vous me donner quelques conseils sur la façon de gérer efficacement le timing sur l'Arduino.

/* 
Timer2_Counter_display_time_elapsed.ino 
Timer2 Counter Basic Example - Demonstrates use of my Timer2_Counter, which is a timer function with 0.5us precision, 
rather than 4us precision like the built-in Arduino micros() function has. 
By Gabriel Staples 
Visit my blog at http://electricrcaircraftguy.blogspot.com/ 
-My contact info is available by clicking the "Contact Me" tab at the top of my blog. 
-Please support my work & contributions by buying something here: https://sites.google.com/site/ercaguystore1/ 
My original post containing this code can be found here: http://electricrcaircraftguy.blogspot.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html 
Written: 17 May 2014 
Updated: 30 May 2014 
*/ 

//CODE DESCRIPTION: 
//This code demonstrates the use of my Timer2, which provides a more precise timer than micros(). 
//micros() has a precision of only 4us. However, Timer2 keeps track of time to a precision of 0.5us. 
//This is especially important in my code which reads an RC receiver PWM signal, which varies from 900~2100us. 
//Though this code demonstrates the use of the Timer_2 functions I have written, it does not adequately demonstrate the 
//real utility of the code, so I will state the following: 
//By using my Timer2 timer to measure the PWM high time interval on an RC receiver, in place of using micros(), I can get repeatable 
//pulse width reads with a fluctuation of ~1us, rather than having a read-in range fluctuating by as much as +/- 4~8 us when I use micros(). 
//This is an increase in precision of ~8x. 

//include the library 
#include <eRCaGuy_Timer2_Counter.h> 
#define pin_output 2 
#include <time.h> 

//Note: an object of this class was already pre-instantiated in the .cpp file of this library, so you can simply access its methods (functions) 
//  directly now through the object name "timer2" 
//eRCaGuy_Timer2_Counter timer2; //this is what the pre-instantiation line from the .cpp file looks like 

boolean on=false; 
int values[24][32]={0}; 
int one_output =1680; 
int zero_output= 560; 

void low_output(int); 
void high_output(int); 
void start_protocol(int); 
void end_protocol(int); 


void setup() { 
    //configure Timer2 
    timer2.setup(); //this MUST be done before the other Timer2_Counter functions work; Note: since this messes up PWM outputs on pins 3 & 11, as well as 
    //interferes with the tone() library (http://arduino.cc/en/reference/tone), you can always revert Timer2 back to normal by calling 
    //timer2.unsetup() 
    //values[0]={8,4,1,5,8,6}; 
    //prepare serial 
    Serial.begin(115200); 
    pinMode(pin_output, OUTPUT); 
    digitalWrite(pin_output, HIGH); 
    //Output a header of info: 
    /*Serial.println(F("Notes:")); 
    Serial.println(F("micros() has a precision of 4us")); 
    Serial.println(F("get_count() with unsigned long final data type has a final precision of 1us, and is fast")); 
    Serial.println(F("get_count() with float final data type has a final precision of 0.5us, and is not quite as fast")); 
    Serial.println(F("get_micros() has a precision of 0.5us, and is slower than the above 2 methods, so one of the above 2 methods is preferred")); 
    Serial.println(F("=============================================="));*/ 
} 


void loop() { 
    //declare local variables 
    delay(2000); 
    start_protocol(); 
    low_output(8); 
    high_output(4); 
    low_output(1); 
    high_output(5); 
    low_output(8); 
    high_output(6); 
    end_protocol(); 
    static unsigned long t_start = timer2.get_count(); 
    // unsigned long t_micros = micros(); 
    unsigned long t_T2_count = timer2.get_count(); 
    //float t_T2_micros = timer2.get_micros(); 
    if ((t_T2_count - t_start)/2 >= 2000003) 
    { 
     digitalWrite(pin_output, HIGH); 
    } 
} //end of loop() 


void low_output(int xtimes) 
{ 
    for (int i =0 ; i<xtimes ; i++){ 
     static unsigned long t_start = timer2.get_count(); //units of 0.5us; the count accumulated by Timer2_Counter 

     //acquire time stamps 

     unsigned long t_T2_count = timer2.get_count(); //units of 0.5us; the count accumulated by Timer2_Counter 

     //See if 1.000003 seconds has elapsed. If so, print out the time stamps. Note: I am using this elapsed time because I want it to NOT be divisible by 4, so that 
     //you can hopefully see the extra precision provided by the Timer2_Counter library, which the default Arduino micros() function does not have 
     if ((t_T2_count - t_start)/2 >= zero_output)//1000003) //if 1.000003 seconds has elapsed 
     { 
      t_start = t_T2_count; //update start time 
      if(on==false) { 
       digitalWrite(pin_output, LOW); 
       on=true; 
      }else { 
       digitalWrite(pin_output, HIGH); 
       on=false; 
      } 

     } 
    } 
    return; 
} 


void high_output(int xtimes) 
{ 
    for (int i =0 ; i<xtimes ; i++){ 
     static unsigned long t_start = timer2.get_count(); 

     //acquire time stamps 

     unsigned long t_T2_count = timer2.get_count(); 


     if ((t_T2_count - t_start)/2 >= one_output) 
     { 
      t_start = t_T2_count; //update start time 
      if(on==false) { 
       digitalWrite(pin_output, LOW); 
       on=true; 
      }else { 
       digitalWrite(pin_output, HIGH); 
       on=false; 
      } 

     } 
    } 
    return; 
} 


void start_protocol(){ 

    static unsigned long t_start = timer2.get_count(); 
    unsigned long t_T2_count = timer2.get_count(); 
    digitalWrite(pin_output, LOW);  


    t_start = timer2.get_count(); 
    t_T2_count = timer2.get_count(); 
    if ((t_T2_count - t_start)/2 >= 9000) 
    { 
     digitalWrite(pin_output, HIGH); 
    } 

} 


void end_protocol(){ 

    static unsigned long t_start = timer2.get_count(); 
    unsigned long t_T2_count = timer2.get_count(); 
    if ((t_T2_count - t_start)/2 >= zero_output) 
    { 
     digitalWrite(pin_output, LOW); 
    } 

    t_start = timer2.get_count(); 
    t_T2_count = timer2.get_count(); 
    if ((t_T2_count - t_start)/2 >= 40000) 
     digitalWrite(pin_output, HIGH); 

    t_start = timer2.get_count(); 
    t_T2_count = timer2.get_count(); 
    if ((t_T2_count - t_start)/2 >= 9000) 
    { 
     digitalWrite(pin_output, LOW); 
    } 
    t_start = timer2.get_count(); 
    t_T2_count = timer2.get_count(); 
    if ((t_T2_count - t_start)/2 >= 2100) 
    { 
     digitalWrite(pin_output, HIGH); 
    } 
    t_start = timer2.get_count(); 
    t_T2_count = timer2.get_count(); 
    if ((t_T2_count - t_start)/2 >= zero_output) 
    { 
     digitalWrite(pin_output, LOW); 
    } 
    digitalWrite(pin_output, HIGH); 
} 

Pour ce code, j'ai utilisé une bibliothèque de synchronisation faite par Gabriel Staples. Après avoir suivi les conseils de @Gmodjackass, le code suivant a reçu le signal NEC sur la sortie de la broche 2. Remarque: le code peut être optimisé en ajoutant un support pour la manipulation directe du port de broche.

#define pin_output 2 
#include <time.h> 

boolean on=false; 
int values[24][32]={0}; 
int one_output =1680; 
int zero_output= 560; 
int sb=-1; 
void low_output(int); 
void high_output(int); 
void start_protocol(); 
void end_protocol(); 
void selection_protocol(String); 
void setup() { 

    Serial.begin(115200); 
    pinMode(pin_output, OUTPUT); 
    digitalWrite(pin_output, HIGH); 
    Serial.print("user_inpu: on(1)/off(0)"); 
    delayMicroseconds(400); 
} 

void loop() { 
    //declare local variables 
    if (Serial.available()) 
    { 

     char sb = Serial.read(); 
     Serial.print(sb); 
     switch (sb){ 
     case '0': 
      selection_protocol("off"); 
      break; 
     case '1': 
      selection_protocol("on"); 
      break; 

     } 
     sb=-1; 
    } 
} //end of loop() 

void low_output(int xtimes) 
{ 
    for (int i =0 ; i<xtimes*2 ; i++){   
     if(on==false) { 
      digitalWrite(pin_output, LOW); 
      on=true; 
     }else { 
      digitalWrite(pin_output, HIGH); 
      on=false; 
     } 
     delayMicroseconds(zero_output); 
     //} 
    } 
    return; 
} 
void high_output(int xtimes) 
{ 
    for (int i =0 ; i<xtimes*2 ; i++){  
     if(on==false) { 
      digitalWrite(pin_output, LOW); 
      on=true; 
      delayMicroseconds(zero_output); 
     }else { 
      digitalWrite(pin_output, HIGH); 
      on=false; 
      delayMicroseconds(one_output); 
     } 
     //} 
    } 
    return; 
} 
void start_protocol(){ 
    digitalWrite(pin_output, LOW);  
    delayMicroseconds(9000); 
    digitalWrite(pin_output, HIGH); 
    delayMicroseconds(4400); 


    return; 
} 
void end_protocol(){ 

    digitalWrite(pin_output, LOW); 
    delayMicroseconds(zero_output);   
    digitalWrite(pin_output, HIGH); 
    delay(40);   
    digitalWrite(pin_output, LOW); 
    delayMicroseconds(9000);  
    digitalWrite(pin_output, HIGH); 
    delayMicroseconds(2100);  
    digitalWrite(pin_output, LOW); 
    delayMicroseconds(zero_output); 
    digitalWrite(pin_output, HIGH); 
    return; 
} 
void selection_protocol(String user_input){ 

    if(user_input == "on"){ 
     Serial.print("on selected"); 
     start_protocol(); 
     low_output(8); 
     high_output(4); 
     low_output(1); 
     high_output(5); 
     low_output(8); 
     high_output(6); 
     end_protocol(); 
    } 
    if(user_input == "off"){ 
     Serial.print("off selected"); 
     start_protocol(); 
     low_output(8); 
     high_output(4); 
     low_output(1); 
     high_output(3); 
     low_output(1); 
     high_output(1); 
     low_output(6); 
     high_output(1); 
     low_output(1); 
     high_output(6); 
     end_protocol(); 

    } 
    return; 
} 

Répondre

0

Certains de vos écarts de temps peut être causé par la nature très lente des digitalWrite de arduino, peut-être regarder en utilisant direct port manipulation. Pensez également à utiliser ce delay function à la place, car cela pourrait causer plus de problèmes de synchronisation.

(modifié pour les fautes d'orthographe)

+0

merci pour les conseils :), je vais vérifier pour et mettre à jour le code si le résultat fonctionne. – Fernand

+0

@Jonathan Leffler merci pour l'édition – Fernand