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:
#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:
#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
Jambe
March 21, 2020, 1:29pm
2
Sans nous donner le résultat du moniteur série, pas évident de donner une réponse
Bonjour,
Je n'avais pas vu votre réponse, désolé.
Le résultat de la console donne ça.
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.
kamill
March 31, 2020, 6:48pm
4
Bonjour,
Ça correspond à quoi le /75 dans la formule?
rpm = 30 * 1000 / (millis() - timeold) * rpmcount / 75;
Je pense que la vitesse en rpm devrait être
rpm = 30 * 1000 / (millis() - timeold) * rpmcount ;
kamill:
Bonjour,
Ça correspond à quoi le /75 dans la formule?
rpm = 30 * 1000 / (millis() - timeold) * rpmcount / 75;
Je pense que la vitesse en rpm devrait être
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.
kamill
April 11, 2020, 3:47pm
6
Ça donne un résultat correct sans le /75 ?
kamill:
Ç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 !
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:
/*
+-\/-+
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:
#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:
0
0
0
0
0
kamill
April 11, 2020, 5:54pm
9
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.
Si je comprend bien dans l'attiny, je devrais écrire:
i2c_regs[1] = rpm >> 8;
i2c_regs[0] = rpm & 0xFF;
Et dans le Uno:
if (Wire.available())
{
hb=Wire.read();
lb=Wire.read();
}
//int rpm=word(hb,lb);
int rpm = (lb << 8) | hb;
C'est ça ?
kamill
April 11, 2020, 6:22pm
11
Oui pour l'envoi, mais autant les mettre dans l'ordre
i2c_regs[0] = rpm & 0xFF; // poids faible
i2c_regs[1] = rpm >> 8; // poids fort
Pour la réception
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.
kamill:
Oui pour l'envoi, mais autant les mettre dans l'ordre
i2c_regs[0] = rpm & 0xFF; // poids faible
i2c_regs[1] = rpm >> 8; // poids fort
Pour la réception
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:
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
kamill
April 11, 2020, 7:38pm
14
Avec plaisir. Bonne continuation.