Topic "Communiquer sans fil en 433MHz avec la bibliothèque VirtualWire et une carte Arduino / Genuino"

Flux RSS des posts récents dans ce topic ( Flux Atom)


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#180 | Signaler ce message


Dans un précédent article, je vous avais montré comment utiliser un module radio complet, riche en fonctionnalités. Dans ce tutoriel, nous allons voir plus petit et plus low-cost en utilisant de simples modules de communication radio 433MHz à quelques euros pièce. Nous verrons quand et comment utiliser ces modules et comment les mettre en oeuvre avec la bibliothèque Arduino VirtualWire. En bonus, nous verrons comment fabriquer une télécommande sans fil simpliste.

Lire la suite de l'article sur le site

Derniére modification le par skywodd


Pas de photo de profil

fabien

Membre

#281 | Signaler ce message


Bonjour, Merci pour votre article très complet. J'ai un petit problème concernant cette librairie: Je souhaite utiliser un Attiny 85 comme transmetteurs et un arduino nano comme récepteur afin de transmettre des chiffres (float), mais cela ne marche pas, j'ai essayé mon code entre un UNO et un NANO et il fonctionne très bien, vérifié mes branchements une centaine de fois ^^ il n'y a pas de problème… Faut il ajouter une autre librairie sur Attiny ? Comment trouver une solution à ce problème ?

Voici mon code pour Attiny:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <VirtualWire.h>

void setup() {

  vw_setup(2000);
  vw_set_tx_pin(1);
}
 
void loop() {

  float valeur = 204;
  
  vw_send((byte *) &valeur, sizeof(valeur)); 
  vw_wait_tx();
}

Et celui du NANO:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <VirtualWire.h>

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

  vw_setup(2000);
  vw_rx_start(); 

  Serial.println("Go !"); 
}

void loop() {

  float valeur;
  byte taille_message = sizeof(float);

  vw_wait_rx();

  if (vw_get_message((byte *) &valeur, &taille_message)) {

    Serial.println(valeur);
  }
}

Merci infiniment de votre aide !

Edit Skywodd : Ajout des balises code.

Derniére modification le par skywodd


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#283 | Signaler ce message


Bonjour,

Est-ce que tu as tenté d'envoyer un simple caractère pour voir si l’émission fonctionne de base avec l'Attiny ?

N.B. L'appel à la fonction vw_set_tx_pin() devrait être avant vw_setup().


Pas de photo de profil

fabien

Membre

#286 | Signaler ce message


Bonjour,

L'envoi de caractères ne marche pas non plus, même une simple lettre …

Merci


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#287 | Signaler ce message


L'envoi de caractères ne marche pas non plus, même une simple lettre …

par fabien

Tu as un oscilloscope sous la main pour vérifier qu'il y a un signal en sortie de la broche ?

L'appel à vw_set_tx_pin() est bien avant vw_setup() dans ton code ?


Pas de photo de profil

fabien

Membre

#288 | Signaler ce message


L'envoi de caractères ne marche pas non plus, même une simple lettre …

par fabien

Tu as un oscilloscope sous la main pour vérifier qu'il y a un signal en sortie de la broche ?

L'appel à vw_set_tx_pin() est bien avant vw_setup() dans ton code ?

par skywodd

Non pas d'oscilloscope malheureusement, seulement un multimètre… J'ai bien changé le code mais pas plus de resultat…


Photo de profil de mneo31

mneo31

Membre

#307 | Signaler ce message


Bonjour,
moi j'ai un souci avec le transfère de structure.
Coter émetteur aucuns bug, mais coté récepteur au bout de X réception ça plante.
Je m'explique :
J'envoi une structure composer de 4 variables, 3 float et 1 unsigned int.
Au bout d'un moment le récepteur ne met plus a jours les variables correctement.
Je reset l'arduino récepteur et ça repart pour un moment puis bug.
Pour le moment j'ai bricolé un bout de code qui reset l'arduino en cas de bug, mais j'aimerai que ça fonctionne normalement.
Une idée???
Les infos envoyer sont, deux températures (float), pression (float) et un compteur (unsigned int).
Le compteur est la pour géré mon auto reset du récepteur ( il sera supprimé quand le bug sera résolue).

J'ai essayer de passé ma structure en variable volatile, ça met plus de temps avant de planté.
Tout le programme tourne normalement (c'est juste les variables de la structure qui ne ce mette plus a jours).
Un bug de Virtualwire??? je n'ai jamais eu ce problème avec l'envoi/réception de chaines de caractères.
Le programme récepteur affiche simplement sur un LCD 16x2.
Température d'un 18b20 branché sur l'arduino et les valeurs des sondes de l'émetteur (via ma structure décrite plus haut) .

Je précise que ce n'ai pas un problème de signal ou de porté (j'ai testé avec un fil à la place des modules RF et le bug est toujours là ).
J'ai fait le tour de tout, j'ai même vérifier que sur le récepteur il n'y ai pas un problème de ram, via un bout de code qui informe de la taille de la ram disponible à la demande.
Je n'ai plus d'idée. Merci d'avance.

PS pour Virtualwire avec un attiny 85 il faut faire quelque modification dans le .cpp de la librairie .
Au niveau de la configuration du timer utiliser par virtualwire (il y a un bug avec le timer 0, il faut utiliser le timer1 ) et dans le .h pour modifier la taille du buffer utiliser par virtualwire (sinon il prend trop de ram).

Ps: je peut envoyer les codes récepteur et émetteur, idem pour la modification de la librairie de virtualwire pour l'ami fabien.

PS "encore", j'utilise deux arduino uno pour mon couple émetteur et récepteur.

PS "Fabien" question as tu essayé avec un simple fil pour relier l'attiny et l'arduino ?
Quel est la configuration de l'attiny 85 ? (les fusibles, fréquence d'horloge et type d'horloge)

Derniére modification le par mneo31


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#310 | Signaler ce message


Au bout d'un moment le récepteur ne met plus a jours les variables correctement. Je reset l'arduino récepteur et ça repart pour un moment puis bug.

par mneo31

Ce serait possible de voir le code TX et RX ? On dirait bien qu'il y a un bug côté récepteur. J'ai ma petite idée sur son origine (j'ai déjà eu un probléme similaire par le passé).

PS pour Virtualwire avec un attiny 85 il faut faire quelque modification dans le .cpp de la librairie. Au niveau de la configuration du timer utiliser par virtualwire (il y a un bug avec le timer 0, il faut utiliser le timer1 ) et dans le .h pour modifier la taille du buffer utiliser par virtualwire (sinon il prend trop de ram).

par mneo31

Ce serait possible d'avoir un lien vers les modif en questions ? Ce serait un bon sujet d'article ;)


Photo de profil de mneo31

mneo31

Membre

#311 | Signaler ce message


Au bout d'un moment le récepteur ne met plus a jours les variables correctement. Je reset l'arduino récepteur et ça repart pour un moment puis bug.

par mneo31

Ce serait possible de voir le code TX et RX ? On dirait bien qu'il y a un bug côté récepteur. J'ai ma petite idée sur son origine (j'ai déjà eu un probléme similaire par le passé).

PS pour Virtualwire avec un attiny 85 il faut faire quelque modification dans le .cpp de la librairie. Au niveau de la configuration du timer utiliser par virtualwire (il y a un bug avec le timer 0, il faut utiliser le timer1 ) et dans le .h pour modifier la taille du buffer utiliser par virtualwire (sinon il prend trop de ram).

par mneo31

Ce serait possible d'avoir un lien vers les modif en questions ? Ce serait un bon sujet d'article ;)

par skywodd

Le TX

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <SPI.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>

#include "Timer.h"
Timer t;
/*
Cayenne Ethernet Example

This sketch connects to the Cayenne server using an Arduino Ethernet Shield W5100
and runs the main communication loop.

The Cayenne Library is required to run this sketch. If you have not already done so you can install it from the Arduino IDE Library Manager.

Steps:
1. Set the token variable to match the Arduino token from the Dashboard.
2. Compile and upload this sketch.

For Cayenne Dashboard widgets using digital or analog pins this sketch will automatically
send data on those pins to the Cayenne server. If the widgets use Virtual Pins, data
should be sent to those pins using virtualWrites. Examples for sending and receiving
Virtual Pin data are under the Basics folder.
*/

//#define CAYENNE_DEBUG         // Uncomment to show debug messages
#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space
#include <CayenneEthernet.h>
#define W5200_CS  10 // pin EN W5200
#define SDCARD_CS 4 //pin EN SDCARD


#include <OneWire.h>
#include <DallasTemperature.h>
#include <VirtualWire.h>

#include <Wire.h>
#include <BMP085.h>

// Cayenne authentication token. This should be obtained from the Cayenne Dashboard.
char token[] = "MON TOKEN";
byte arduino_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress arduino_ip(192, 168, 1, 177);
IPAddress dns_ip(8, 8, 8, 8);
IPAddress gateway_ip(192, 168, 1, 1);
IPAddress subnet_mask(255, 255, 255, 0);


// Virtual Pin of the DS18B20 widget.
#define VIRTUAL_PIN V0

// Virtual Pins of the BMP180 widget.
#define BAROMETER_PIN V1
#define TEMPERATURE_PIN V2

BMP085 bmp;

// Digital pin the DS18B20 is connected to. Do not use digital pins 0 or 1 since those conflict with the use of Serial.
const int tmpPin = 17;

OneWire oneWire(tmpPin);
DallasTemperature sensors(&oneWire);

typedef struct {
  float realTemperature; //temperature BMP180
  float realPressure; //Pression BMP180
  float temp; //Termperature 18b20
  unsigned int count; //variable compteur pour auto reset du recepteur (a supprimer quand bug résolue)
} Mastructure;

Mastructure ms;
byte taille_ms = sizeof(Mastructure);

void setup()
{
  Serial.begin(9600);
  vw_setup(2000);//vitesse 2000bps
  vw_set_tx_pin(7);//DATA TX
  pinMode(5, OUTPUT); //GND TX
  pinMode(6, OUTPUT); //VCC TX
  pinMode(7, OUTPUT); //DATA TX
  digitalWrite(5, LOW); //GND TX
  digitalWrite(6, HIGH); //VCC TX


  pinMode(SDCARD_CS, OUTPUT); //AUSSI VCC TX
  pinMode(W5200_CS, OUTPUT);
  pinMode(15, OUTPUT);//GND 18B20
  pinMode(16, OUTPUT);//VCC 18B20
  digitalWrite(15, 0);
  digitalWrite(16, 1);
  digitalWrite(W5200_CS, HIGH); // init W5200
  digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card
  Cayenne.begin(token, arduino_ip, dns_ip, gateway_ip, subnet_mask, arduino_mac);
  bmp.begin(BMP085_ULTRA_HIGH_RES);
  bmp.setSoftwareOversampling(1);

  sensors.begin();
  sensors.setResolution(12);

  t.every(20000, envoi); //timer pour envoi périodique 433 (n'utilise pas de timer hardware)
  ms.count = 0;
}

void loop()
{
  Cayenne.run();
  t.update();
}

// This function is called when the Cayenne widget requests data for the Virtual Pin.
CAYENNE_OUT(BAROMETER_PIN)
{
  ms.realPressure = bmp.readFloatPressure();
  Cayenne.virtualWrite(BAROMETER_PIN,  ms.realPressure / 100); // diviser par 100 pour avoir une sortie hPa

}

// This function is called when the Cayenne widget requests data for the temperature's Virtual Pin.
CAYENNE_OUT(TEMPERATURE_PIN)
{

  ms.realTemperature = bmp.readFloatTemperature();
  // Send the value to Cayenne in Celsius.
  Cayenne.celsiusWrite(TEMPERATURE_PIN, ms.realTemperature);

}
CAYENNE_OUT(VIRTUAL_PIN)
{
  // Send the command to get temperatures.
  sensors.requestTemperatures();
  ms.temp = sensors.getTempCByIndex(0);
  // This command writes the temperature in Celsius to the Virtual Pin.
  Cayenne.celsiusWrite(VIRTUAL_PIN, ms.temp);
  // To send the temperature in Fahrenheit use the corresponding code below.
  //Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}

void envoi() {
  ms.count++; 
  vw_send((uint8_t *) &ms, sizeof(ms));
  vw_wait_tx(); // Wait until the whole message is gone
  
  //debug
  Serial.print(F("Pression = "));
  Serial.println(ms.realPressure / 100);
  Serial.print(F("Temperature BMP180 = "));
  Serial.println(ms.realTemperature);
  Serial.print(F("Temperature 18B20 = "));
  Serial.println(ms.temp);
  Serial.print(F("ms.count = "));
  Serial.println(ms.count);
  Serial.print(F("----------"));
  Serial.print(millis() / 1000);
  Serial.println(F(" Seconds----------"));
}



Le code du RX :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <avr/wdt.h> //pour l'auto reset
#include <DFR_Key.h>

#include <LiquidCrystal.h>
#include <VirtualWire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 17  //DATA DS (module 17 , TO92 16)

#include "Timer.h"
Timer t;

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DFR_Key keypad;

typedef struct {
  float realTemperature;//tempertature bmp180
  float realPressure;//perssion bmp180
  float temp;//temperature 18b20
  unsigned int count;//compteur pour auto reset
} Mastructure;

Mastructure ms;
byte taille_ms = sizeof(Mastructure);

byte mess = 0;//(variable pour l'affichage alternatif sur la ligne 0 du LCD)

unsigned int verifcount = 0;//compteur local pour auto reset

long oldtime = 0;//variable pour les boutons (temporisation lumiere lcd)
byte erreur = 0;//nombre d'erreur de reception (via count et verficount)

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup() {

  Serial.begin(9600);
  lcd.begin(16, 2);              // start the library
  lcd.setCursor(0, 0);
  sensors.begin();
  sensors.setResolution(12);
  vw_setup(2000);//vitesse 2000bps
  pinMode(10, OUTPUT); // light LCD
  vw_set_tx_pin(11); // data RX
  vw_set_ptt_pin(13);
  pinMode(15, OUTPUT); //gnd ds
  pinMode(16, OUTPUT); // vcc ds  (pour module)
  pinMode(12, OUTPUT); //vcc rx
  pinMode(2, OUTPUT); //gnd rx
  pinMode(3, INPUT); //data rx
  pinMode(18, INPUT_PULLUP); //entrée LDR (A4)
  pinMode(19, OUTPUT); // masse LDR  (A5)
  digitalWrite(19, LOW);
  digitalWrite(12, 1); // vcc rx
  digitalWrite(2, 0); //gnd rx
  digitalWrite(15, 0); //gnd ds18b20
  digitalWrite(16, 1);// vcc ds18b20 (pour module)
  digitalWrite(10, 1);// light LCD

  keypad.setRate(10);

  vw_rx_start();
  //delay(2000);
  oldtime = millis();
  oldtime += 5000;
  t.every(2000, LCD);//timer pour affichage alternatif sur la ligne 0
}

void LCD() {//alterne l'affichage sur la ligne 0 et raffraichie la ligne1 (une fois sur deux)
  sensors.requestTemperatures();//demande la température du 18b20 local
  if (mess == 0) { //affiche la température du 18b20 local
    lcd.setCursor(0, 0);
    lcd.print(sensors.getTempCByIndex(0));
    lcd.write(0xdf);//affiche le symbole °
    lcd.print(F("C"));
    lcd.print(F(":DS"));
    lcd.print(ms.count);
    lcd.print(F("   "));
    mess = 1;
  } else if (mess == 1) {// affiche la préssion du bmp180 externe (433)
    lcd.setCursor(0, 0);
    lcd.print(F("   "));
    lcd.print(ms.realPressure / 100);
    lcd.print(F("hPa   "));
    mess = 0;
    lcd.setCursor(0, 1);//affiche la température du 18b20 et du bmp180 externe (433)
    lcd.print(ms.temp);
    lcd.write(0xdf);
    lcd.print(F("C "));
    lcd.print(ms.realTemperature);
    lcd.write(0xdf);
    lcd.print(F("C"));
  }
}


void loop() {
  t.update();
  recev();

  if (keypad.getKey() > 0) { //détection jour/nuit et forçage éclairage lcd pendant 5sec quand appuis sur un bouton
    digitalWrite(10, 1);
    oldtime = millis();
    oldtime += 5000;
  }// fin if

  if ((analogRead(4) < 300) ) digitalWrite(10, 1);
  else if (oldtime < millis()) digitalWrite(10, 0);

}



void recev() {//message reçu ??? si oui le copie dans ma structure et l'affiche sur le lcd

  if (vw_get_message((byte*) &ms, &taille_ms)) // Non-blocking
  {
    verifcount++;//variable mise a jour pour l'auto reset (si 433 bug)
    Serial.print(F("sizeof(Mastructure) = "));
    Serial.println(sizeof(Mastructure));
    lcd.setCursor(0, 1);
    lcd.print(ms.temp);
    lcd.write(0xdf);
    lcd.print(F("C "));
    lcd.print(ms.realTemperature);
    lcd.write(0xdf);
    lcd.print(F("C"));

    //debug
    Serial.print(F(" ms.realTemperature = "));
    Serial.println(ms.realTemperature);
    Serial.print(F(" ms.realPressure/100 = "));
    Serial.println(ms.realPressure / 100);
    Serial.print(F(" ms.temp = "));
    Serial.println(ms.temp);
    Serial.print(F("ms.count = "));
    Serial.println(ms.count);
    Serial.print(F("----------"));
    Serial.print(millis() / 1000);
    Serial.println(F(" Seconds----------"));
    //Serial.print(F("FREE RAM = "));
    //Serial.println(freeRam());

    if (verifcount == 0) verifcount = ms.count; //si variable à 0 alors on vient de boot on synchronise les deux compteurs
    if (verifcount != ms.count) {//si variable local et distant différente
      lcd.setCursor(0, 1);
      lcd.print(F("ERREUR ERREUR"));//on affiche erreur sur la ligne 1 du lcd
      verifcount = ms.count;//on synchronise les compteurs
      erreur++;//on incrémente la variable erreur
      vw_rx_stop();//on stop la reception
      delay(2000);//on attend 2sec
      vw_rx_start();//on relance la reception    (NB,de stopé et relancé la reception, parfois ça marche mais pas toujours)
    }
  }
  if (erreur == 3) {//Si on a atteind 3 erreur de reception alors on reboot (reset) via le watchdog
    MCUSR = 0; // reboot logiciel
    wdt_disable(); // reboot logiciel
    wdt_enable(WDTO_15MS); //reboot logiciel
  }
}
/* //bout de code pour voir la ram libre au moment ou l'on appel la fonction
int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}*/



Voila mes programmes, pour le coté émetteur cayennes fait des demandes des valeurs des sondes très régulièrement
(1 à 5 sec entre les demandes). Mais le problème ne vient pas de l'émetteur. (d'après moi).

Je vais faire un autre poste pour virtualwire car pas de lien, j'ai utilisé la doc atmel
de l'attiny 85 pour voir quel registre modifier et comment.
( en comparant a la doc du 328 et du code d'origine de la lib)

Derniére modification le par mneo31


Photo de profil de mneo31

mneo31

Membre

#312 | Signaler ce message


Les modifications pour virtualwire

Déjà il faut savoir que sur un attiny 85 nous n'avons que 2 timers
et non pas 3 comme sur un arduino à base de atmega328.
De plus nous avons moins de flash 8kb pour l'attiny 85 contre 32Kb pour le 328
Nous avons moins de ram 512bytes pour l'attiny 85 contre 2Kb pour le 328.
Et nous pouvons avoir une fréquence CPU différente selon la programmation des fusibles de l'attiny 85.
Moi personnellement j'utilise souvent le mode PLL interne
pour avoir une fréquence CPU à 16Mhz sur l'attiny.
Quand je n'ai pas besoin de puissance de calcule (programme simple sans librairie complexe)
je tourne en 8Mhz interne, voir quand j'ai besoin d'une faible consommation 1Mhz.
Pour la modification de virtualwire, j'en revient a l'histoire des timers.
Par défaut virtualwire utilise le timer 0 ce qui fait "planté" les
fonctions tel que millis(), delay(), mais pas que!
toute les librairies utilisant ces fonctions sont aussi impacté,
parfois ça ne pose pas de problème si les tempos sont modifier
mais souvent ça interfère dans le bon déroulement du programme.
D'autant que si vous utilisé une autre librairie et qu'elle aussi utilise le timer 0. Là c'est la pagaille car seul la librairie initialisé en dernier aura le dernier mot sur le paramétrage du timer 0.

Dans la librairie, j'ai modifier l'utilisation du timer,
afin d'utilisé le timer 1 et non plus le timer 0. La taille du buffer (nombre d'octet pouvant être envoyer ou reçu), à adapter selon vos besoins.
A savoir, plus le buffer est grand, plus il prend de la place dans la ram.
Maintenant les modifications :
la partie dans le .h modifier: //pour la taille du buffer

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// These defs cause trouble on some versions of Arduino
#undef abs
#undef double
#undef round

#ifndef VW_MAX_MESSAGE_LEN 
 #ifdef __AVR_ATtiny85__
  #define VW_MAX_MESSAGE_LEN 20  //80 init for 328p
  #else
/// Maximum number of bytes in a message, counting the byte count and FCS
    #define VW_MAX_MESSAGE_LEN 80  //80 init
    #endif
#endif //VW_MAX_MESSAGE_LEN 

Dans le .cpp :
Le code d'origine pour utiliser le timer 0

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void vw_setup(uint16_t speed)
{
    uint16_t nticks; // number of prescaled ticks needed
    uint8_t prescaler; // Bit values for CS0[2:0]

#ifdef __AVR_ATtiny85__
    // figure out prescaler value and counter match value
    prescaler = vw_timer_calc(speed, (uint8_t)-1, &nticks);
    if (!prescaler)
    {
        return; // fault
    }

    TCCR0A = 0;
    TCCR0A = _BV(WGM01); // Turn on CTC mode / Output Compare pins disconnected

    // convert prescaler index to TCCRnB prescaler bits CS00, CS01, CS02
    TCCR0B = 0;
    TCCR0B = prescaler; // set CS00, CS01, CS02 (other bits not needed)

    // Number of ticks to count before firing interrupt
    OCR0A = uint8_t(nticks);

    // Set mask to fire interrupt when OCF0A bit is set in TIFR0
    TIMSK |= _BV(OCIE0A);

A remplacer par ça : pour utiliser le timer 1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void vw_setup(uint16_t speed)
{
    uint16_t nticks; // number of prescaled ticks needed
    uint8_t prescaler; // Bit values for CS0[2:0]

#ifdef __AVR_ATtiny85__
    // figure out prescaler value and counter match value
    prescaler = vw_timer_calc(speed, (uint8_t)-1, &nticks);
    if (!prescaler)
    {
        return; // fault
    }
    PLLCSR = 0; // ck clock not pll clock


    TCCR1 = 0;
    TCCR1 = _BV(CTC1); // Turn on CTC mode / Output Compare pins disconnected

    // convert prescaler index to TCCRnB prescaler bits CS00, CS01, CS02
    //TCCR0B = 0;
   // TCCR0B = prescaler; // set CS00, CS01, CS02 (other bits not needed)
    if (prescaler == 1) {
    TCCR1 = _BV(CS10);
    }
    else if (prescaler == 2) {
    TCCR1 = _BV(CS12);
    }
    else if (prescaler == 3) {
    TCCR1 = _BV(CS10);
    TCCR1 = _BV(CS11);
    TCCR1 = _BV(CS12);
    }
    else if (prescaler == 4) {
    TCCR1 = _BV(CS13);
    TCCR1 = _BV(CS10);
    }
    else if (prescaler == 5) {
    TCCR1 = _BV(CS10);
    TCCR1 = _BV(CS11);
    TCCR1 = _BV(CS13);
    }
    // Number of ticks to count before firing interrupt
    OCR1A = uint8_t(nticks);
    OCR1C = OCR1A;

    // Set mask to fire interrupt when OCF0A bit is set in TIFR0
    TIMSK |= _BV(OCIE1A);



Pour la configuration du timer on ne peut pas copier coller la méthode
utiliser pour le timer 0 sur le timer 1 car les prescalers du timer 0 sont différent
des prescalers du timer 1. Voir doc atmel. Pages 80 et 89/90.
Voila, ne pas hésiter a me contacter si besoin.

Derniére modification le par skywodd


Photo de profil de mneo31

mneo31

Membre

#313 | Signaler ce message


L'envoi de caractères ne marche pas non plus, même une simple lettre …

par fabien

Tu as un oscilloscope sous la main pour vérifier qu'il y a un signal en sortie de la broche ?

L'appel à vw_set_tx_pin() est bien avant vw_setup() dans ton code ?

par skywodd


Non pas d'oscilloscope malheureusement, seulement un multimètre… J'ai bien changé le code mais pas plus de resultat…

par fabien

Je pense a un truc! Dans la loop tu envois en boucle essaie de rajouter un delay(2000); après le vw_wait_tx();
Et pense a notifier la broche RX avec vw_set_rx_pin(broche); sur le récepteur (même si tu utilise la broche par défaut)
Tu devrais rajouter un bout de code dans la loop (faire clignoté une led) pour voir que le programme tourne effectivement.

As tu déjà programmer des attiny pour des programmes plus "simple" genre simplement faire clignoté une led a une fréquence donner? (genre un clignotement par seconde) si oui, as tu vérifier que la fréquence de clignotement programmé dans ton code corresponde bien à celle observé sur ton montage?

Si ça ne correspond pas il faut vérifier quel est l'horloge du attiny (réglage des fusibles).

J'ai eu avec un attiny et virtualwire (mais je ne pense pas que ça soit le cas dans ton programme car très léger) c'est un débordement de la ram (par défaut virtualwire utilise un "buffer" de 80 octets)
Dernier cas, j'avais un conflit avec le timer0 (utiliser par virtualwire et une seconde librairie dans mon code). Idem ce n'ai pas le cas dans ton code.

Si tu connais assez bien l'IDE arduino, tu as du forcément rajouter les fichiers board pour programmer les attiny, il faudrait surement creusé de ce coté là. (réglages des fusibles de l'attiny, core utiliser, variante utiliser ect) si tu manipules bien c'est fichiers dans l'IDE il serai bien de faire toi même une config pour attiny a rajouter dans ta liste de board.

Exemple de ma board maison pour les attiny

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
menu.cpu=Processor
menu.clock=Clock

attiny.name=ATtiny
attiny.bootloader.tool=arduino:avrdude
attiny.bootloader.unlock_bits=0xff
attiny.bootloader.lock_bits=0xff
attiny.build.core=arduino:arduino
attiny.build.board=attiny
attiny.upload.tool=arduino:avrdude

attiny.menu.cpu.attiny45=ATtiny45
attiny.menu.cpu.attiny45.upload.maximum_size=4096
attiny.menu.cpu.attiny45.build.mcu=attiny45
attiny.menu.cpu.attiny45.build.variant=tiny8

attiny.menu.cpu.attiny85=ATtiny85
attiny.menu.cpu.attiny85.upload.maximum_size=8192
attiny.menu.cpu.attiny85.build.mcu=attiny85
attiny.menu.cpu.attiny85.build.variant=tiny8

attiny.menu.cpu.attiny85A=ATtiny85 SPECIAL
attiny.menu.cpu.attiny85A.upload.maximum_size=8192
attiny.menu.cpu.attiny85A.build.mcu=attiny85
attiny.menu.cpu.attiny85A.build.variant=tiny

attiny.menu.cpu.attiny44=ATtiny44
attiny.menu.cpu.attiny44.upload.maximum_size=4096
attiny.menu.cpu.attiny44.build.mcu=attiny44
attiny.menu.cpu.attiny44.build.variant=tiny14

attiny.menu.cpu.attiny84=ATtiny84
attiny.menu.cpu.attiny84.upload.maximum_size=8192
attiny.menu.cpu.attiny84.build.mcu=attiny84
attiny.menu.cpu.attiny84.build.variant=tiny14

attiny.menu.clock.internal1=1 MHz (internal BOD 1.8V)
attiny.menu.clock.internal1.bootloader.low_fuses=0x62
attiny.menu.clock.internal1.bootloader.high_fuses=0xd6
attiny.menu.clock.internal1.bootloader.extended_fuses=0xff
attiny.menu.clock.internal1.build.f_cpu=1000000L

attiny.menu.clock.internal8=8 MHz (internal BOD 2.7V)
attiny.menu.clock.internal8.bootloader.low_fuses=0xe2
attiny.menu.clock.internal8.bootloader.high_fuses=0xd5
attiny.menu.clock.internal8.bootloader.extended_fuses=0xff
attiny.menu.clock.internal8.build.f_cpu=8000000L

attiny.menu.clock.internal8d=8 MHz (internal BOD DISABLED)
attiny.menu.clock.internal8d.bootloader.low_fuses=0xe2
attiny.menu.clock.internal8d.bootloader.high_fuses=0xd7
attiny.menu.clock.internal8d.bootloader.extended_fuses=0xff
attiny.menu.clock.internal8d.build.f_cpu=8000000L

attiny.menu.clock.internal16=16 Mhz PLL (internal BOD 2.7V)
attiny.menu.clock.internal16.bootloader.low_fuses=0xF1
attiny.menu.clock.internal16.bootloader.high_fuses=0xd5
attiny.menu.clock.internal16.bootloader.extended_fuses=0xff
attiny.menu.clock.internal16.build.f_cpu=16000000L

attiny.menu.clock.external8=8 MHz (external)
attiny.menu.clock.external8.bootloader.low_fuses=0xfe
attiny.menu.clock.external8.bootloader.high_fuses=0xdf
attiny.menu.clock.external8.bootloader.extended_fuses=0xff
attiny.menu.clock.external8.build.f_cpu=8000000L

attiny.menu.clock.external16=16 MHz (external)
attiny.menu.clock.external16.bootloader.low_fuses=0xfe
attiny.menu.clock.external16.bootloader.high_fuses=0xdf
attiny.menu.clock.external16.bootloader.extended_fuses=0xff
attiny.menu.clock.external16.build.f_cpu=16000000L

attiny.menu.clock.external20=20 MHz (external)
attiny.menu.clock.external20.bootloader.low_fuses=0xfe
attiny.menu.clock.external20.bootloader.high_fuses=0xdf
attiny.menu.clock.external20.bootloader.extended_fuses=0xff
attiny.menu.clock.external20.build.f_cpu=20000000L


Ce qui me donne dans la sélection du type de carte la possibilité de choisir type de carte attiny
Puis quel attiny (45 85 44 84) (dont un attiny 85 spécial, pour palier a un bug de SoftwareSerial sur l'affectation des broches)
Puis de sélectionné quel horloge je veux . 1Mhz , 8Mhz , 16Mhz , 20Mhz
Interne ou externe et avec différent réglage de BOD selon la fréquence .

Comme ça je sais comment sont configurés les fusibles de mon attiny et j'évites les problèmes du a des fusibles mal configurer.
PS si tu ne manipules pas bien les fichiers board.txt, ne cherche pas a copier coller mon code, car il manque les fichiers .h .cpp et .c lier au fichier board.txt
Mais ça peut peut-être inspiré l'admin du blog alias Skywodd.


Pas de photo de profil

fabien

Membre

#316 | Signaler ce message


Bonjour,

Merci beaucoup pour tes messages, je n'ai pas tout compris mais dans l'ensemble je pense savoir d'où vient le problème.

J'ai déjà programmé sur ATtiny (Led, bouton, potentiomètre…etc) donc ce n'est pas dans la programmation qu'il y a un problème.

J'ai Upload le programme "blink", tout se passe bien, si j'ajoute la librairie <VirtualWire>, ça ne change rien, elle clignote toujours à la bonne fréquence mais si j'ajoute "vw_setup(1000);" la led ne clignote plus à la bonne frequence…

Je vais donc des maintenant modifier le .h et le .cpp comme tu me l'as conseillé et on verra bien…

J'ai eu accès à un oscilloscope cette semaine, il y a bien un signal en sortie qui ressemble de loin à celui en sortie du UNO.

Et petite question: comment savoir à quelle frequence programme le ATtiny ?

Merci beaucoup !


Pas de photo de profil

fabien

Membre

#317 | Signaler ce message


J'ai modifier le .cpp et le .h et… ça ne marche pas, ça ne veux pas compiler…


Pas de photo de profil

fabien

Membre

#319 | Signaler ce message


J'ai remarqué une erreur que j'avais faite dans les modifications, je peux maintenant compiler, mais la led ne clignote plus du tout, elle ne s'allume même plus…


Photo de profil de mneo31

mneo31

Membre

#320 | Signaler ce message


J'ai modifier le .cpp et le .h et… ça ne marche pas, ça ne veux pas compiler…

par fabien

Quels sont les erreurs, lors de la compilation ?

Pour savoir à quel vitesse d'horloge tourne ton attiny85, normalement tu le sais quand tu sélectionnes le type de composant (pense aussi a graver la séquence d'initialisation) qui pour un attiny 85 est en faite la programmation des fusibles ( car il n'y a pas de bootloader ).
Comme expliquer dans mon poste précédent, moi je me suis fait une liste pour les attiny "maison", mais si tu as récupéré une configuration sur le net pour programmer les attiny, il est normalement indiqué la fréquence quand tu le sélectionnes dans ta liste ( je parle de la liste ou tu sélectionnes la carte que tu programmes, arduino uno, arduino nano..ect)
Et vérifie bien que ton arduino RX et ton attiny TX soit bien avec la même vitesse de vw_setup(1000);


Photo de profil de mneo31

mneo31

Membre

#321 | Signaler ce message


J'ai remarqué une erreur que j'avais faite dans les modifications, je peux maintenant compiler, mais la led ne clignote plus du tout, elle ne s'allume même plus…

par fabien

Quel est ton programme de test ?

Peux tu le posté.
Merci


Pas de photo de profil

fabien

Membre

#322 | Signaler ce message


Alors ça marche… dans certain cas:

La transmission fonction uniquement si le ATtiny est programmé avec une clock:8Mhz et ce code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
/**
 * Exemple de code pour la bibliothèque VirtualWire – Client d'envoi de variable
 */
 
#include <VirtualWire.h>

void setup() {

  vw_set_tx_pin(0);
  vw_setup(1000);
}
 
void loop() {
  
  float valeur = 9;
  
  vw_send((byte *) &valeur, sizeof(valeur)); // On envoie le message
  vw_wait_tx(); // On attend la fin de l'envoi
}

L'arduino uno en reception utilise la librairie sans modification:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <VirtualWire.h>

void setup() {
  Serial.begin(9600);
  vw_set_rx_pin(11);
  vw_setup(1000);
  vw_rx_start();

  Serial.println("Go !"); 
}

void loop() {
  float valeur;
  byte taille_message = sizeof(float);
  
  vw_wait_rx();
  if (vw_get_message((byte *) &valeur, &taille_message)) {

    Serial.println(valeur);
  }
  
}

Cependant le test avec la led n'est pas concluant, celui ci ne fonctionne d'avec une clock de 1Mhz et un vw_setup(2000), dans les autres cas, la led clignote très vite, très lentement voir pas du tout.

Voici le code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <VirtualWire.h>

void setup() {

  vw_set_tx_pin(1);
  vw_setup(2000);

  pinMode(0, OUTPUT);
}

void loop() {
  digitalWrite(0, HIGH);   
  delay(1000);             
  digitalWrite(0, LOW);    
  delay(1000);            
}

Voila voila, donc la transmission fonctionne mais pas le clignotement de la LED.

Merci

Edit modérateur: modification des balises code pour avoir la coloration syntaxique.

Derniére modification le par skywodd


Photo de profil de mneo31

mneo31

Membre

#323 | Signaler ce message


Alors ça marche… dans certain cas:

La transmission fonction uniquement si le ATtiny est programmé avec une clock:8Mhz et ce code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
/**
 * Exemple de code pour la bibliothèque VirtualWire – Client d'envoi de variable
 */
 
#include <VirtualWire.h>

void setup() {

  vw_set_tx_pin(0);
  vw_setup(1000);
}
 
void loop() {
  
  float valeur = 9;
  
  vw_send((byte *) &valeur, sizeof(valeur)); // On envoie le message
  vw_wait_tx(); // On attend la fin de l'envoi
}

L'arduino uno en reception utilise la librairie sans modification:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <VirtualWire.h>

void setup() {
  Serial.begin(9600);
  vw_set_rx_pin(11);
  vw_setup(1000);
  vw_rx_start();

  Serial.println("Go !"); 
}

void loop() {
  float valeur;
  byte taille_message = sizeof(float);
  
  vw_wait_rx();
  if (vw_get_message((byte *) &valeur, &taille_message)) {

    Serial.println(valeur);
  }
  
}

Cependant le test avec la led n'est pas concluant, celui ci ne fonctionne d'avec une clock de 1Mhz et un vw_setup(2000), dans les autres cas, la led clignote très vite, très lentement voir pas du tout.

Voici le code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <VirtualWire.h>

void setup() {

  vw_set_tx_pin(1);
  vw_setup(2000);

  pinMode(0, OUTPUT);
}

void loop() {
  digitalWrite(0, HIGH);   
  delay(1000);             
  digitalWrite(0, LOW);    
  delay(1000);            
}

Voila voila, donc la transmission fonctionne mais pas le clignotement de la LED.

Merci

par fabien

OK
Pour le attiny virtualwire + led, le test est fait avec la version modifier de virtualwire? (pour qu'il utilise le timer 1 et non le timer 0). Et inutile de modifier ou non pour l'arduino , car la lib utilise la modification seulement pour les attiny 85 (dans le .cpp on a un #ifdef __AVR_ATtiny85__) donc la modif ne marche pas pour un arduino ou un autre attiny (comme un 45 par ex).
C'est très étrange que la led ne clignote pas normalement avec virtualwire modifier, car le but est justement de laisser le timer0 pour les fonctions delay millis ect…
Concernant la vitesse d'horloge du attiny, faire les testes avec une horloge à 8Mhz (ou 16Mhz si disponible) en interne. Après il faut la choisir en fonction de ce qu'on programme et si la consommation du attiny est importante ou pas.

+1 pour le test à 1Mhz, ça montre bien que le timer 0 ce trouve modifier (il ne devrait pas pourtant)
Tu programmes bien un attiny 85?

Je ne pense pas que virtualwire fonction avec une clock à 1Mhz (jamais testé perso), normalement il marche pour 8Mhz et 16Mhz (testé et approuvé sur attiny 85).


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#327 | Signaler ce message


Je laisse de côté le forum une seconde et paf, 11 notifications. Je vais avoir du boulot :D

@mneo31: Je ne vois pas d'erreur dans ton code TX, quelques améliorations possibles, mais rien de plus.

Je vois par contre une grosse erreur dans le code du RX ;)

1
2
3
4
5
6
7
8
// Variables globales
Mastructure ms;
byte taille_ms = sizeof(Mastructure);

// Dans la fonction recv()
if (vw_get_message((byte*) &ms, &taille_ms)) {
...
}

La fonction vw_get_message() met à jour la valeur de la variable taille_ms passé en argument pour qu'elle corresponde avec la taille du message reçu (cf article).

Or, si le message est corrompu, celui-ci ne fera pas la bonne taille. Tu me vois venir ? A l'appel suivant, la valeur taille_ms n'est plus à jour. Tu écris donc potentiellement en dehors de la structure et ça plante.

Déplace la déclaration de la variable taille_ms dans le corps de la fonction recv(). Ça devrait résoudre ton probléme.

Je pense a un truc! Dans la loop tu envois en boucle essaie de rajouter un delay(2000); après le vw_wait_tx();

Ce n'est pas un soucis, la fonction vw_wait_tx() s'occupe déjà d'attendre la fin de la transmission avec d'en commencer une nouvelle.

Cependant, un délai supplémentaire serait effectivement le bienvenue pour ne pas bloquer complètement la porteuse 433MHz en envoyant continuellement des messages, mais en soit, ça ne devrait pas être la cause du soucis (au pire c'est un élément aggravant).

Cependant le test avec la led n'est pas concluant, celui ci ne fonctionne d'avec une clock de 1Mhz et un vw_setup(2000), dans les autres cas, la led clignote très vite, très lentement voir pas du tout.

Je suis de l'avis de mneo31, ça sent la modification involontaire du timer 0 lors de l'initialisation de VirtualWire. La LED ne devrait pas s’arrêter de clignoter après un simple appel à vw_setup().

Question bête : tu as relancé l'IDE Arduino après avoir fait la modif ? Les bibliothèques de code ne sont mise à jour qu'au démarrage du logiciel.


Photo de profil de mneo31

mneo31

Membre

#328 | Signaler ce message


Je laisse de côté le forum une seconde et paf, 11 notifications. Je vais avoir du boulot :D

@mneo31: Je ne vois pas d'erreur dans ton code TX, quelques améliorations possibles, mais rien de plus.

Je vois par contre une grosse erreur dans le code du RX ;)

1
2
3
4
5
6
7
8
// Variables globales
Mastructure ms;
byte taille_ms = sizeof(Mastructure);

// Dans la fonction recv()
if (vw_get_message((byte*) &ms, &taille_ms)) {
...
}

La fonction vw_get_message() met à jour la valeur de la variable taille_ms passé en argument pour qu'elle corresponde avec la taille du message reçu (cf article).

Or, si le message est corrompu, celui-ci ne fera pas la bonne taille. Tu me vois venir ? A l'appel suivant, la valeur taille_ms n'est plus à jour. Tu écris donc potentiellement en dehors de la structure et ça plante.

Déplace la déclaration de la variable taille_ms dans le corps de la fonction recv(). Ça devrait résoudre ton probléme.

Je pense a un truc! Dans la loop tu envois en boucle essaie de rajouter un delay(2000); après le vw_wait_tx();

Ce n'est pas un soucis, la fonction vw_wait_tx() s'occupe déjà d'attendre la fin de la transmission avec d'en commencer une nouvelle.

Cependant, un délai supplémentaire serait effectivement le bienvenue pour ne pas bloquer complètement la porteuse 433MHz en envoyant continuellement des messages, mais en soit, ça ne devrait pas être la cause du soucis (au pire c'est un élément aggravant).

Cependant le test avec la led n'est pas concluant, celui ci ne fonctionne d'avec une clock de 1Mhz et un vw_setup(2000), dans les autres cas, la led clignote très vite, très lentement voir pas du tout.

Je suis de l'avis de mneo31, ça sent la modification involontaire du timer 0 lors de l'initialisation de VirtualWire. La LED ne devrait pas s’arrêter de clignoter après un simple appel à vw_setup().

Question bête : tu as relancé l'IDE Arduino après avoir fait la modif ? Les bibliothèques de code ne sont mise à jour qu'au démarrage du logiciel.

par skywodd
@Skywodd:


Je laisse de côté le forum une seconde et paf, 11 notifications. Je vais avoir du boulot :D

Avec moi surtout qui poste souvent des tartines…..

La fonction vw_get_message() met à jour la valeur de la variable taille_ms passé en argument pour qu'elle corresponde avec la taille du message reçu (cf article).

Je vois l'idée et j'y avais pensé, j'ai commencé par faire un serial.print pour vérifier la valeur de taille_ms. Aucun problème, elle ne change pas.
J'ai ensuite fixé la valeur (ici) 3 floats + 1 unsigned int = 4 x 4 = 16.
Idem la variable ne change pas dans le temps, et le bug est toujours présent.

NOTA: j'avais un bug sur le setup du TX vw_set_tx_pin(11); // data RX or c'est vw_set_rx_pin(11); // data RX
j'ai corrigé l'erreur, mais ça n'a rien changer. J'ai mis la main sur un mini librairie (Arduino Easy Transfer) , l'idée est simple, et correspond plus ou moins à mon ajout de compteur pour vérifier la bonne transmission des données (sauf que là on a deux variable fixe et une variable de checksum).
J'ai donc fait un autre test (deux en un) un attiny 85 en TX et un nano en RX.
- l'attiny 85 envoi 4 variables (unsigned int) unit0 unit1 unit2 unit3 il fait un random pour unit0 et unit1 puis unit2 = unit0 - unit1 et unit3 = unit0 + unit2.
Sur le nano il vérifie que le calcule mathématique est bon pour validé les données reçu, et là ! aucun bug !
Donc je ne sais toujours pas de ou ça provient.

Pour le delay(2000) il est inutile cas dans mon TX la fonction void envoi() n'ai appelé qu'une fois toute les 20sec environ. Je vais testé avec un envoi de tableau (vu que dans mon cas actuel, je n'envoi que des floats).

@Fabien:


Pour le attiny 85 j'ai remarqué quelques choses , selon tes fichiers board pour le attiny 85 , il utilise soit le timer0 pour millis delay ect…. soit le timer1 !!!! dans mon cas j'utilise le timer1 ce qui entre en conflit avec virtualwire (si j'utilise en parallèle les fonctions millis, delay…).
Extrait de mon code UserTimer.h dans mes fichiers board pour les attiny :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
*=============================================================================
  Assume there are only two timers.  One for millis and one for everything 
  else.
=============================================================================*/

#if TIMER_TO_USE_FOR_MILLIS == 0
#define TIMER_TO_USE_FOR_USER                     1
#elif TIMER_TO_USE_FOR_MILLIS == 1
#define TIMER_TO_USE_FOR_USER                     0
#else
#error Unexpected condition in UserTimer.h.
#endif


On vois bien que si on ne précise rien il utilise le timer1 pour millis (donc pour delay).
Pour changer le choix du timer utilisé il faut modifier ce bout de code dans le fichier core_build_option.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*=============================================================================
  Build options for the ATtiny85 processor
=============================================================================*/

#if defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ )
#define __AVR_ATtinyX5__
#endif

#if defined( __AVR_ATtinyX5__ )

/*
  For various reasons, Timer 1 is a better choice for the millis timer on the
  '85 processor.
*/
#define TIMER_TO_USE_FOR_MILLIS                   1

/*
  If the following is true (non-zero) there will be two phase-correct PWM 
  pins and one fast PWM pin.  If false there will be one phase-correct PWM 
  pin and two fast PWM pins.
*/
#define FAVOR_PHASE_CORRECT_PWM                   1

/*
  Tone goes on whichever timer was not used for millis.
*/
#if TIMER_TO_USE_FOR_MILLIS == 1
#define TIMER_TO_USE_FOR_TONE                     0
#else
#define TIMER_TO_USE_FOR_TONE                     1
#endif

#define HAVE_ADC                                  1

#define DEFAULT_TO_TINY_DEBUG_SERIAL              1

#endif


La ligne

1
#define TIMER_TO_USE_FOR_MILLIS                   1


Tu changes le 1 en 0, mais attention !!! Pour les mêmes raisons qu'il est mieux d'utilisé le timer1 pour virtualWire c'est aussi valable pour millis.
Explication : Le timer0 est (moins précis) que le timer1.
Pourquoi ? Car le timer0 possède moins de choix de prescaler que le timer1.
Prescaler c'est un réglage qui permet de diviser pas X la fréquence d'horloge pour "créé" une horloge spécifique pour le timer. Exemple : tu a une horloge configuré à 8Mhz, et un prescaler réglé à 1024, tu auras donc sur le timer une horloge de 8Mhz / 1024 soit une horloge d'environ 7812Hz.
Pour le timer0 on à le choix entre 1 , 8 , 64 , 256 , 1024
Pour le timer1 on à le choix entre 1 ,2 ,4 ,8 ,16 ,32 ,64 ,128 ,256 ,512 ,1024 ,2048 ,4096 ,8192 ,16384.
Donc forcément on peut "régler" plus précisément le timer1 quand il s'agit de compté un intervalle de temps comme c'est la cas pour virtualWire et Millis.
Donc sache que si tu utilises le timer0 pour millis, tu perdras un peu en précision pour les fonctions rattaché (millis, delay notamment).Ce n'ai pas un drame non plus! ça peut être un problème si tu as besoin d'une bonne précision par exemple pour l'utilisation de capteurs ultrasons pour mesuré une distance, ça marchera, mais ça sera moins précis.
J'ai remarqué un bug sur les attiny, il faut passé la broche utilisé en TX en pinMode(brocheTX,OUTPUT); Car je ne sais pas pourquoi, la librairie ne le fait pas.


NOTE du 16/11/2016 19h50
Je n'ai pas totalement résolut le problème d'envoi de structure, MAIS, j'ai remarqué qu'en fixant la valeur de taille_ms
Voici la ligne de code :

1
  if (vw_get_message((byte*) &ms, &taille_ms)) // Non-blocking 


Donc juste avant le if je défini la valeur de taille_ms et ça ne ce bloque plus.
En revanche j'ai un autre problème, maintenant j'ai par moment des valeurs "farfelu" sur mes variables en réception (Oui oui, module chinois en 433Mhz) quelque soit la distance de 30cm à 15m.
Chose étrange, je n'ai pas plus de bug à 15m qu'a 30cm.
Il faut que je test avec un fil entre les deux arduino à la place des modules 433Mhz. Aux prochaines news….

NOTE : 19/11/2016 18h00
J'ai passé la vitesse de 2000 à 200 bps, encore quelques erreurs de transmission, mais ça va bien mieux (7 erreurs sur 24H) , toujour le problème avec les structures (résolut en partie, maintenant seul la dernière variable de la structure bug de temps en temps).
Je n'ai pas encore testé avec un fil à la place des modules 433Mhz. Affaire à suivre.

NOTE: 22/11/2016 16h35
Remarque :
En trouvant un bug sur la carte nano avec l'utilisation du watchdog pour le reset automatique (il ne marche pas avec le bootloader d'origine) , j'ai donc changer de bootloader pour un optiboot et faire fonctionné mon reset software, et là ! bug avec virtualwire et les structures. J'ai donc de nouveau charger le bootloader d'origine sur la nano. Et quasiment plus de bug avec virtualwire. (je pense que les bugs restant vienne d'un problème de communication entre les modules 433).
Donc en résumé, je pense que le bug initial sur mes UNO vient du bootloader (car sur les UNO avec le bootloader d'origine le reset soft marche)
Et comme sur mes NANO avec le bootloader d'origine je n'ai pas de bug avec virtualwire et les structures (mise a part ceux du au problème de communication entre les modules 433).
Quand j'ai un bug du au module 433, la lib le note dans son compteur d'erreur de réception (ce n'ai pas le cas sur le UNO).
Question : quel parti du bootloader peut faire planté la réception de structure via virtualwire?
Comment créé son bootloader (passé du .c au .hex). Via Atmelstudio? ou possible avec la suite arduino IDE?
Possible de mettre le bootloader du nano sur le UNO et inversement ? (je sais le faire, mais ça va fonctionné ?)
Je pars du principe que ce sont tout les deux des atmega328.

L'idée c'est de me composé un bootloader perso, qui prend le reset software sans faire planté virtualwire et les structures et de le collé dans tout les arduino à base de atmega328 (UNO, NANO). J'attends vos lumières.

NOTE: 22/11/2016 17h27
Je viens de voir que dans l'arduino UNO on charge le bootloader OPTIBOOT.
Donc en faite quand je change le bootloader de ma NANO pour pouvoir utilisé le watchdog reset je vient collé le bootloader de la UNO. J'ai un peu regarder les .C des deux bootloader, ça me pique les yeux !
NOTE: 23/11/2016 14h00
Malgré le bootloader d'origine sur la NANO, j'ai maintenant les mêmes bug que sur la UNO avec les structures.
Je ne comprend pas pourquoi ça avais fonctionné quelques jours sans bug majeur avec la NANO (avant que je change puis remette le bootloader d'origine). Donc le problème doit malgré tout être lié au bootloader (car quand je parle de celui d'origine, je parle de celui qui ce patch quand on sélectionne la board NANO dans l'IDE arduino, je n'avais peu être pas la même version dans ma NANO avant modification ).
J'ai encore une NANO non modifier sous la main, je vais essayer avec voir ce que ça donne. (si quelqu'un sait comment on peu "voir" la version du bootloader installé dans la NANO).

Derniére modification le par mneo31