Arduino Forum

International => Français => Topic started by: pierrotm777 on Mar 21, 2020, 12:52 pm

Title: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Mar 21, 2020, 12:52 pm
Bonjour,

J'essaie de réaliser un compte tour .
Un attiny85 utilise un capteur IR GP2Y0D810Z0F et envoie le résultat à l'Uno via le port I2C.

Ca semble fonctionner mais le résultat sur le port série de l'Uno semble bizarre.

Voici donc le code de L'attiny85 en configuration esclave:
Code: [Select]


#include "TinyWireS.h"      // ATTiny wire lib
#include "PinChangeInterrupt.h"
           
#define I2C_SLAVE_ADDR  0x26           
#define Sensor_PIN  1
#define Led_PIN     4
boolean firstbyte = true;

volatile byte rpmcount;
unsigned int rpm;
unsigned long timeold;

void setup() {
  pinMode(Sensor_PIN,INPUT);
  TinyWireS.begin(I2C_SLAVE_ADDR);
  TinyWireS.onRequest(requestEvent);
  attachPCINT(Sensor_PIN, rpm_fall, FALLING);
  rpmcount = 0;
  rpm = 0;
  timeold = 0;
}

void rpm_fall()
{
  rpmcount++;  //Each rotation, this interrupt function is run twice
}

void loop()
{
  if (rpmcount >= 250)
  {
    //Update RPM every 20 counts, increase this for better RPM resolution,
    //decrease for faster update
    rpm = 30*1000/(millis() - timeold)*rpmcount/75;
    timeold = millis();
    rpmcount = 0;
  } 
  if (digitalRead(Sensor_PIN) == LOW)
  {
    digitalWrite(Led_PIN,HIGH);
  }
  else
  {
    digitalWrite(Led_PIN,LOW);
  }
}


void requestEvent()
{

  byte plow;
  byte phi;
 
  if(firstbyte == true)
  {     // on the first byte we do the math
   plow=lowByte(rpm);
   firstbyte = false;      //so next time though we send the next byte   
   TinyWireS.send(plow);
  }
  else
  {
   phi=highByte(rpm);
   TinyWireS.send(phi);
   firstbyte = true;
  }
}


et le code de l'Uno en configuration maître:
Code: [Select]
#include "Wire.h";
int ATtinyAddress=0x26;
unsigned long marktime;

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


void loop(){
 if (millis()>marktime)
 {
   byte hb;
   byte lb;
   Wire.requestFrom(ATtinyAddress,2);
   if (Wire.available())
   {
     lb=Wire.read();
     hb=Wire.read();
   }
   int rpm=word(hb,lb);
   Serial.println (rpm);
   marktime+=1000;
 }
}


Pourriez me dire quel est mon erreur svp .

Merci de votre aide par avance.

Pierre
Title: Re: Copte tour avec liaison I2C entre Attiny85 et Uno
Post by: Jambe on Mar 21, 2020, 02:29 pm
Sans nous donner le résultat du moniteur série, pas évident de donner une réponse
Title: Re: Copte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Mar 31, 2020, 01:29 pm
Bonjour,

Je n'avais pas vu votre réponse, désolé.
Le résultat de la console donne ça.


Code: [Select]
36
36
36
36
36
33
33
33
33
33
33
33
30
30
30
30
30
30
30
26
26
26
26
26
26
30
30
30
30
30
30
30
30
30
30


Mon ventilo de PC tourne au moins à 1000 tr/mn je pense donc , ya un bug.
Title: Re: Copte tour avec liaison I2C entre Attiny85 et Uno
Post by: kamill on Mar 31, 2020, 08:48 pm
Bonjour,

Ça correspond à quoi le /75 dans la formule?
Code: [Select]
   rpm = 30 * 1000 / (millis() - timeold) * rpmcount / 75;
Je pense que la vitesse en rpm devrait être
Code: [Select]
   rpm = 30 * 1000 / (millis() - timeold) * rpmcount ;
Title: Re: Copte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Apr 11, 2020, 04:42 pm

Bonjour,

Ça correspond à quoi le /75 dans la formule?
Code: [Select]
   rpm = 30 * 1000 / (millis() - timeold) * rpmcount / 75;
Je pense que la vitesse en rpm devrait être
Code: [Select]
   rpm = 30 * 1000 / (millis() - timeold) * rpmcount ;
Désolé pour le délais.
Je ne reçois pas d'alerte. C'est bizarre.

Je pense que oui.
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: kamill on Apr 11, 2020, 05:47 pm
Ça donne un résultat correct sans le /75 ?
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Apr 11, 2020, 06:35 pm
Ça donne un résultat correct sans le /75 ?
J'ai été interrompu par des courses :-)
Je regarde ça dès que possible et vous rend compte !
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Apr 11, 2020, 07:16 pm
Alors, j'ai essayé dans un premier temps de commenter le code du compte tour pour n'envoyer que rpm = 10000 via l'I2C.
Pour l'attiny85 j'ai simplifié ainsi:
Code: [Select]
/*


                  +-\/-+
             NC  1|    |8  VCC (2.7-5.5V)
             NC  2|    |7  I2C   SCK -> Uno A5
            LED  3|    |6  (PB1) SENSOR
            GND  4|    |5  I2C   SDA -> Uno A4
                  +----+
*/

#include "TinyWireS.h"      // ATTiny wire lib
#include "PinChangeInterrupt.h"
           
#define I2C_SLAVE_ADDR  0x26           
#define Sensor_PIN  1
#define Led_PIN     4
boolean firstbyte = true;

volatile byte rpmcount;
volatile unsigned int rpm;
unsigned long timeold;

#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif
volatile uint8_t i2c_regs[] =
{
    0, //older 8
    0 //younger 8
};
volatile byte reg_position = 0;
const byte reg_size = sizeof(i2c_regs);


void setup() {
//  pinMode(Sensor_PIN,INPUT);
  TinyWireS.begin(I2C_SLAVE_ADDR);
  TinyWireS.onRequest(requestEvent);
//  attachPCINT(Sensor_PIN, rpm_fall, FALLING);
//  rpmcount = 0;
//  rpm = 0;
//  timeold = 0;
}

//void rpm_fall()
//{
//  rpmcount++;  //Each rotation, this interrupt function is run twice
//}

void loop()
{
//  if (rpmcount >= 250)
//  {
    //Update RPM every 20 counts, increase this for better RPM resolution,
    //decrease for faster update
    rpm = 10000;//30*1000/(millis() - timeold)*rpmcount;//rpm = 30*1000/(millis() - timeold)*rpmcount/75;
    i2c_regs[0] = rpm >> 8;
    i2c_regs[1] = rpm & 0xFF;   
    //timeold = millis();
    //rpmcount = 0;

   
   
//  } 
//  if (digitalRead(Sensor_PIN) == LOW)
//  {
//    digitalWrite(Led_PIN,HIGH);
//  }
//  else
//  {
//    digitalWrite(Led_PIN,LOW);
//  }
}


void requestEvent()

  TinyWireS.send(i2c_regs[reg_position]);

  reg_position++;
  if (reg_position >= reg_size)
  {
      reg_position = 0;
  }
}


Pour le Uno:
Code: [Select]
#include "Wire.h";
int ATtinyAddress=0x26;
unsigned long marktime;

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


void loop(){
 if (millis()>marktime)
 {
   byte hb;
   byte lb;
   Wire.requestFrom(ATtinyAddress,2);
   if (Wire.available())
   {
     lb=Wire.read();
     hb=Wire.read();
   }
   //int rpm=word(hb,lb);
   int rpm = (lb << 8) | hb;
   //int rpm = ((lb * 16 + hb) / 16) / 4;
   Serial.println (rpm);
   marktime+=1000;
 }
}


Le Uno me retourne 0:
Code: [Select]
0
0
0
0
0
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: kamill on Apr 11, 2020, 07:54 pm
Ca doit fonctionner.
A part le fait que tu te mélanges les pinceaux entre low byte et high byte. Tu transmets le high byte en premier et quand tu reçois le low byte en premier.
Comme il y a inversion aussi dans le calcul 'int rpm = (lb << 8) | hb' ça compense la première erreur.
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Apr 11, 2020, 08:11 pm
Si je comprend bien dans l'attiny, je devrais écrire:
Code: [Select]
    i2c_regs[1] = rpm >> 8;
    i2c_regs[0] = rpm & 0xFF;


Et dans le Uno:

Code: [Select]
   if (Wire.available())
   {
     hb=Wire.read();
     lb=Wire.read();
   }
   //int rpm=word(hb,lb);
   int rpm = (lb << 8) | hb;


C'est ça ?
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: kamill on Apr 11, 2020, 08:22 pm
Oui pour l'envoi, mais autant les mettre dans l'ordre
Code: [Select]
   i2c_regs[0] = rpm & 0xFF;  // poids faible
   i2c_regs[1] = rpm >> 8;    // poids fort


Pour la réception
Code: [Select]
  if (Wire.available())
  {
    lb=Wire.read();  // poids faible
    hb=Wire.read();  // poids fort
  }
  int rpm=word(hb,lb);


Je ne sais pas pourquoi tu as créé la variable i2c_regs qui ne sert à rien. Ca fonctionnait très bien comme c'était dans ton premier programme.
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Apr 11, 2020, 09:13 pm
Oui pour l'envoi, mais autant les mettre dans l'ordre
Code: [Select]
   i2c_regs[0] = rpm & 0xFF;  // poids faible
   i2c_regs[1] = rpm >> 8;    // poids fort


Pour la réception
Code: [Select]
  if (Wire.available())
  {
    lb=Wire.read();  // poids faible
    hb=Wire.read();  // poids fort
  }
  int rpm=word(hb,lb);


Je ne sais pas pourquoi tu as créé la variable i2c_regs qui ne sert à rien. Ca fonctionnait très bien comme c'était dans ton premier programme.

Cool ça fonctionne :-)

Je reçois bien:
Code: [Select]
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000
10000

Je vais rajouter le compteur de tour

Merci pour le coup de main :-)
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Apr 11, 2020, 09:23 pm
Nickel,


Merci encore ! :)
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: kamill on Apr 11, 2020, 09:38 pm
Avec plaisir.  Bonne continuation.
Title: Re: Compte tour avec liaison I2C entre Attiny85 et Uno
Post by: pierrotm777 on Apr 11, 2020, 09:39 pm
Avec plaisir.  Bonne continuation.
Merci