hi,
i think you have to call the serial communication with the bms in the main programm!
i'll send you the complete code of my project:
- LCD, keys and BMS with I2C
- speed and PAS signals in interrupts
it isn't really finished, but already working like this:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Konstanten-Deklaration
const float umfang = 2070; // Radumfang 26"
const int PAS_magnet = 5; // Anzahl der Magneten im PAS
// Variablen-Deklaration
// LCD
LiquidCrystal_I2C lcd(0x21,20,4); // set the LCD address to 0x21, for a 20 chars and 4 line display
int spos = 0; // spalte 0-20
int zpos = 0; // zeile 0-3
char str1[20] = "E-bike Control V1.1";
char str2[20] = " ";
char z1 = 192; //ascii
char z2 = 192;
// Tastatur (4 Tasten)
boolean T0 = 0;
boolean T1 = 0;
boolean T2 = 0;
boolean T3 = 0;
// IO
int Gas_in_ch = 0; // Ain0 für Gasgriff
int Gas_in = 0;
int Gas_out_ch = 0; // Ain0 für Gasgriff
int Gas_out = 0;
int PAS_in_ch = 2; // Din2 (IRQ0) für PAS-Signal
boolean PAS_in = 0;
int spd_in_ch = 3; // Din3 (IRQ1) für speed-Signal
boolean PAS_alt = 0; // für flanke
unsigned long PAS_1 = 0; // msec
unsigned long PAS_2 = 0; // msec
float PAS = 0; // U/min
float PAS_MW = 0; // gleitender MW
unsigned long PAS_h_time = 0; //Altwert PAS_H millis
unsigned long PAS_l_time = 0; //Altwert PAS_L millis
boolean PAS_dir = 0; // Trittrichtung
unsigned long spd_1 = 0; // msec
float spd = 0;
float spd_MW = 0; // gleitender MW
unsigned long spd_time = 0;
// allgemein
int count = 0; // zähler
int tmp_data = 0;
unsigned long tmp_long = 0;
boolean test = 1; // Testbetrieb
unsigned long time;
boolean temp_bool = 0;
int n1 = 0;
int n2 = 0;
byte val = 0;
// OZ
byte val1 = 0;
byte val2 = 0;
byte adr = 0;
int zelle = 0;
int i2cadr = 0;
byte stat1 = 0;
byte stat2 = 0;
float volt = 0;
float volt1 = 0;
float volt2 = 0;
float volt3 = 0;
float volt4 = 0;
float volt5 = 0;
float volt6 = 0;
float volt7 = 0;
float volt8 = 0;
float voltMIN = 0;
float voltMAX = 0;
float amp = 0;
float watt = 0;
// --------------------------------
// Init
void setup()
{
Serial.begin(9600);
// IO init
pinMode(PAS_in_ch, INPUT_PULLUP);
pinMode(4, OUTPUT);
PAS_l_time = millis();
PAS_h_time = millis();
// Interrupt Din2 ist IRQ 0 (PAS), Din3 ist IRQ 1 (speed)
attachInterrupt(0, irqprg0, CHANGE);
attachInterrupt(1, irqprg1, RISING);
// LCD init
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.setCursor(0,0);
lcd.print(str1); // Print a message to the LCD.
delay(1000);
// lcd.clear();
// Tastatur-PCF8574 auf input
Wire.beginTransmission(0x38);
Wire.write(0xff); // alle IO high
Wire.endTransmission();
// Tastatur einlesen
Wire.requestFrom(0x38, 1);
tmp_data = Wire.read();
T0= (tmp_data & 0x01); // Taste 0 beim Einschalten gedrückt
// test = T0 // -> Testbetrieb
Serial.println(tmp_data);
}
// --------------------------------
// main
void loop()
{
// Zeit
time = millis();
// test
temp_bool = count % 2;
digitalWrite(4,temp_bool);
// Tastatur einlesen
Wire.requestFrom(0x38, 1);
tmp_data = Wire.read();
// Tasten ausmaskieren
T0= (tmp_data & 0x01);
T1= (tmp_data & 0x02) >> 1;
T2= (tmp_data & 0x04) >> 2;
T3= (tmp_data & 0x08) >> 3;
// IOs einlesen
Gas_in = analogRead(Gas_in_ch);
// Erfassung PAS jetzt mit IRQ0
// Drehrichtung fehlt noch
if ((PAS_1 > 0) and (PAS_2 > 0) and ((millis() - PAS_h_time) < 500))
{
// Trittfrequenz in U/min
PAS = 60000/((PAS_1 + PAS_2)*PAS_magnet);
// gleitender Mittelwert
PAS_MW = (PAS_MW * PAS_magnet + PAS)/(1+PAS_magnet);
}
else
{
PAS = 0;
PAS_MW = 0;
}
// PAS_h_time = pulseIn(PAS_in_ch, HIGH);
// PAS_l_time = pulseIn(PAS_in_ch, LOW);
// Erfassung speed mit IRQ1
if (((spd_1 > 50) and (spd_1 < 4000)) and ((millis() - spd_time) < 4000))
{
// Geschwindigkeit in km/h
spd = umfang/spd_1;
// gleitender Mittelwert über 3 Werte
spd_MW = (spd_MW * 3 + spd)/(1+3);
}
else
{
spd = 0;
spd_MW = 0;
}
if (test = 1)
{
// Testprogramm
delay(1000);
// akku einlesen
i2cadr = 0x30; // OZ: adr. 30 statt 60h!!
adr = 0x0; // chip id an adr. 0h
// strom lesen
adr = 0x54; // strom an adr. 54h
// register adresse übermitteln
Wire.beginTransmission(i2cadr);
Wire.write(adr);
stat1 = Wire.endTransmission(false); // 0:sucess
// register daten lesen
stat2 = Wire.requestFrom(i2cadr, 2); // anzahl der gelesenen bytes
val1 = Wire.read();
val2 = Wire.read();
// bytes auswerten
val2 = (val2 & 0x7F); // VZ ausblenden, noch auswerten
amp = 7.63 * (val2 * 256 + val1)/1000; // mV-Spannungsabfall
// Leistung berechnung
watt = amp * volt;
// spannungen lesen
adr = 0x32; // spannung zelle 1 an adr 32h
zelle = 1+count % 8; // für 8 Zellen
adr = adr + 2*(zelle-1);
// register adresse übermitteln
Wire.beginTransmission(i2cadr);
Wire.write(adr);
stat1 = Wire.endTransmission(false); // 0:sucess
// register daten lesen
stat2 = Wire.requestFrom(i2cadr, 2); // anzahl der gelesenen bytes
val1 = Wire.read();
val2 = Wire.read();
// bytes auswerten
val1 = val1/8; // 3 bits ausblenden
val2 = (val2 & 0x7F); // VZ ausblenden
switch (zelle) {
case 1:
volt1 = 1.22 * (val2 * 32 + val1);
break;
case 2:
volt2 = 1.22 * (val2 * 32 + val1);
break;
case 3:
volt3 = 1.22 * (val2 * 32 + val1);
break;
case 4:
volt4 = 1.22 * (val2 * 32 + val1);
break;
case 5:
volt5 = 1.22 * (val2 * 32 + val1);
break;
case 6:
volt6 = 1.22 * (val2 * 32 + val1);
break;
case 7:
volt7 = 1.22 * (val2 * 32 + val1);
break;
case 8:
volt8 = 1.22 * (val2 * 32 + val1);
break;
}
// Gesamt-, MIN und MAX
volt = (volt1+volt2+volt3+volt4+volt5+volt6+volt7+volt8)/1000;
voltMIN = min(volt1,min(volt2,min(volt3,min(volt4,min(volt5,min(volt6,min(volt7,volt8)))))));
voltMAX = max(volt1,max(volt2,max(volt3,max(volt4,max(volt5,max(volt6,max(volt7,volt8)))))));
// Display-ASusgabe
zpos = 1;
spos = 0;
lcd.setCursor(spos,zpos);
// lcd.print(tmp_data);
lcd.print(volt);
lcd.setCursor(5,zpos);
lcd.print(" Tasten: ");
lcd.print(T0);
lcd.print(T1);
lcd.print(T2);
lcd.print(T3);
zpos = 2;
spos = 0;
lcd.setCursor(spos,zpos);
lcd.print(PAS,0);
lcd.setCursor(5,zpos);
lcd.print(PAS_MW,0);
lcd.setCursor(10,zpos);
lcd.print(spd,1);
lcd.setCursor(15,zpos);
lcd.print(spd_MW,1);
zpos = 3;
spos = 0;
lcd.setCursor(spos,zpos);
lcd.print(voltMIN);
lcd.setCursor(10,zpos);
lcd.print(voltMAX);
// debugging
Serial.println(stat1);
Serial.println(val);
Serial.println(stat2);
// Serial.print(PAS_1);
// Serial.print(" ");
// Serial.print(PAS_2);
// Serial.print(" ");
// Serial.print(PAS);
// Serial.print(" ");
// Serial.print(spd);
// Serial.print(" ");
// Serial.print(" ");
// Serial.println(" ");
count = count+1;
}
}
// --------------------------------
// Interruptprogramme
void irqprg0()
// Trittfrequenz PAS-Signale -> Timer
{
PAS_in = digitalRead(PAS_in_ch);
if (PAS_in == 1) //steigend
{
PAS_h_time = millis();
PAS_2 = PAS_h_time - PAS_l_time;
}
else // fallend
{
PAS_l_time = millis();
PAS_1 = PAS_l_time - PAS_h_time;
}
}
void irqprg1()
// speed-Signale -> Timer
{
spd_1 = millis() - spd_time;
spd_time = millis();
}