I2C Problems with Nucleo 64 F103RB

Post here first, or if you can't find a relevant section!
Post Reply
TiMeX
Posts: 2
Joined: Thu Jul 30, 2020 7:30 am

I2C Problems with Nucleo 64 F103RB

Post by TiMeX »

Hey there folks,
I am having some puzzling problems with the I2C bus on my Nucleo 64 STMF103RB board.
My setup: I am trying to communicate with an E-Bike display which acts as the I2C master. The display asks for data at defined addresses (like the index in a data array) in regular intervals and I need to answer these requests with the proper data. I was able to sniff what data gets sent between the display and battery using a I2C sniffer for the Arduino MEGA so I know what my answers should look like. I have written a program for the Arduino UNO to do this and it worked flawlessly.
Now I want to port this program to the STM32F103. The problem is that the STM is not responding to the requests properly. At first the sniffer showed me no activity on the bus apart from the repeated requests from the master, and after some research I found out about clock stretching and how it keeps the SCL line low as long as the STM is still busy. Unfortunately the Display didn't seem to care so I ended up with a constantly LOW SCL line and no responses from my STM.
After I disabled the clock stretching I got some responses but only the second of the two response bytes was correct, the first byte was always something different than it should be. I am now completely out of ideas and hope some of you might be able to help me.

Edit: I am using the STM32duino core from here https://github.com/stm32duino/Arduino_Core_STM32

Sorry for the long post, heres the code of the slave plus the sniffer outputs in the attachments:

Code: Select all

#include <Wire.h>

byte Daten[58];
float array_attiny[29] = {39.3459, 0, 27.85, 16215, 1, 33, 36, 192, 5116, 10734, 15000, 80, 55, 19718, 'ltg7l09450043', 0, 'battery', 'Li-Ion', 49, 225, 84, 0, 0, 10, 255, 0b11000000, 4000, 12450, 255};
int wert = 0;
byte Register;

void setup() {

  Wire.begin(0x0B);                // join i2c bus with address #B
  Wire.onRequest(requestEvent); // register event
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
  Serial.println("Los gehts");

  berechnen();
}

void loop() {
  //delay(300);
  //  Serial.println("Event");
  //  Serial.println(Register, HEX);

}

void berechnen() {

  //für Adresse 09 - Spannung
  wert = round((array_attiny[0] * 1000) / 3.3);
  Daten[0] = wert & 0xFF;
  Daten[1] = (wert >> 8) & 0xFF;

  //für Adresse 10 - Gesamtkapazität
  wert = round(array_attiny[9] / 2);
  Daten[2] = wert & 0xFF;
  Daten[3] = (wert >> 8) & 0xFF;

  //für Adresse 16 - Batteriestatus
  wert = array_attiny[7];
  Daten[4] = wert & 0xFF;
  Daten[5] = (wert >> 8) & 0xFF;

  //für Adresse 0F - verbleibende Kapazität
  wert = round(array_attiny[8] / 2);
  Daten[6] = wert & 0xFF;
  Daten[7] = (wert >> 8) & 0xFF;

  //verbleibende Ladung in Prozent (Restkap)
  wert = array_attiny[11];
  Daten[8] = wert & 0xFF;
  Daten[9] = (wert >> 8) & 0xFF;

  //für Adresse 0A - Strom
  wert = round(array_attiny[1] / 2);
  Daten[10] = wert & 0xFF;
  Daten[11] = (wert >> 8) & 0xFF;

  //für Adresse 08 - Temperatur
  wert = round((array_attiny[2] + 273.15) * 10);
  Daten[12] = wert & 0xFF;
  Daten[13] = (wert >> 8) & 0xFF;

  //für Adresse 1B - Herstelldatum
  wert = array_attiny[3];
  Daten[14] = wert & 0xFF;
  Daten[15] = (wert >> 8) & 0xFF;

  //für Adresse 1C - Seriennummer
  wert = array_attiny[4];
  Daten[16] = wert & 0xFF;
  Daten[17] = (wert >> 8) & 0xFF;

  //für Adresse 17 - Zykluszahl
  wert = array_attiny[5];
  Daten[18] = wert & 0xFF;
  Daten[19] = (wert >> 8) & 0xFF;

  //für Adresse 19 - Werksspannung
  wert = array_attiny[6];
  Daten[20] = wert & 0xFF;
  Daten[21] = (wert >> 8) & 0xFF;

  //für Adresse 0E - absolute Ladung
  wert = array_attiny[12];
  Daten[22] = wert & 0xFF;
  Daten[23] = (wert >> 8) & 0xFF;

  //für Adresse 20 - Herstellername
  wert = array_attiny[13];
  Daten[24] = wert & 0xFF;
  Daten[25] = (wert >> 8) & 0xFF;

  //für Adresse 18 - Werkskapazität
  wert = array_attiny[10];
  Daten[26] = wert & 0xFF;
  Daten[27] = (wert >> 8) & 0xFF;

  //für Adresse 23 - Herstellerdaten
  wert = array_attiny[14];
  Daten[28] = wert & 0xFF;
  Daten[29] = (wert >> 8) & 0xFF;

  //für Adresse 25 - Herstellerinfo
  wert = array_attiny[15];
  Daten[30] = wert & 0xFF;
  Daten[31] = (wert >> 8) & 0xFF;

  //für Adresse 21 - Gerätetyp
  wert = array_attiny[16];
  Daten[32] = wert & 0xFF;
  Daten[33] = (wert >> 8) & 0xFF;

  //für Adresse 22 - Chemie
  wert = array_attiny[17];
  Daten[34] = wert & 0xFF;
  Daten[35] = (wert >> 8) & 0xFF;

  //für Adresse 1A - Spezifikationsinformation
  wert = array_attiny[18];
  Daten[36] = wert & 0xFF;
  Daten[37] = (wert >> 8) & 0xFF;

  //für Adresse 1A - Zeit bis vollgeladen
  wert = array_attiny[19];
  Daten[38] = wert & 0xFF;
  Daten[39] = (wert >> 8) & 0xFF;

  //für Adresse 3F - Spannung Zelle 1
  wert = round(array_attiny[20]);
  Daten[40] = wert & 0xFF;
  Daten[41] = (wert >> 8) & 0xFF;

  //für Adresse 3E - Spannung Zelle 2
  wert = round(array_attiny[21]);
  Daten[42] = wert & 0xFF;
  Daten[43] = (wert >> 8) & 0xFF;

  //für Adresse 3D - Spannung Zelle 3
  wert = round(array_attiny[22]);
  Daten[44] = wert & 0xFF;
  Daten[45] = (wert >> 8) & 0xFF;

  //für Adresse 3C - Spannung Zelle 4
  wert = round(array_attiny[23]);
  Daten[46] = wert & 0xFF;
  Daten[47] = (wert >> 8) & 0xFF;

  //für Adresse 4F - state of health
  wert = array_attiny[24];
  Daten[48] = wert & 0xFF;
  Daten[49] = (wert >> 8) & 0xFF;

  //für Adresse 03 - Batteriemodus
  wert = array_attiny[25];
  Daten[50] = wert & 0xFF;
  Daten[51] = (wert >> 8) & 0xFF;

  //für Adresse 14 - Ladestrom
  wert = round(array_attiny[26]);
  Daten[52] = wert & 0xFF;
  Daten[53] = (wert >> 8) & 0xFF;

  //für Adresse 15 - Ladespannung
  wert = round(array_attiny[27]);
  Daten[54] = wert & 0xFF;
  Daten[55] = (wert >> 8) & 0xFF;

  //für Adresse 2A - Stromregister
  wert = round(array_attiny[28]);
  Daten[56] = wert & 0xFF;
  Daten[57] = (wert >> 8) & 0xFF;
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {

  Register;
  //Spannung
  if (Register == 0x09) {
    Wire.write(Daten[0]);
    Wire.write(Daten[1]);
  }

  //Gesamtkapazität
  if (Register == 0x10) {
    Wire.write(Daten[2]);
    Wire.write(Daten[3]);
  }

  //Batteriestatus
  if (Register == 0x16) {
    Wire.write(Daten[4]);
    Wire.write(Daten[5]);
  }

  //verbleibende Kapazität
  if (Register == 0x0F) {
    Wire.write(Daten[6]);
    Wire.write(Daten[7]);
  }

  //verbleibende Ladung in Prozent (Restkap)
  if (Register == 0x0D) {
    Wire.write(Daten[8]);
    Wire.write(Daten[9]);
  }

  //Strom
  if (Register == 0x0A) {
    Wire.write(Daten[10]);
    Wire.write(Daten[11]);
  }

  //Temperatur
  if (Register == 0x08) {
    Wire.write(Daten[12]);
    Wire.write(Daten[13]);
  }

  //Herstelldatum
  if (Register == 0x1B) {
    Wire.write(Daten[14]);
    Wire.write(Daten[15]);
  }

  //Seriennummer
  if (Register == 0x1C) {
    Wire.write(Daten[16]);
    Wire.write(Daten[17]);
  }

  //Zykluszahl
  if (Register == 0x17) {
    Wire.write(Daten[18]);
    Wire.write(Daten[19]);
  }

  //Werksspannung
  if (Register == 0x19) {
    Wire.write(Daten[20]);
    Wire.write(Daten[21]);
  }

  //absolute Ladung
  if (Register == 0x0E) {
    Wire.write(Daten[22]);
    Wire.write(Daten[23]);
  }

  //Herstellername
  if (Register == 0x20) {
    Wire.write(Daten[24]);
    Wire.write(Daten[25]);
  }

  //Werkskapazität
  if (Register == 0x18) {
    Wire.write(Daten[26]);
    Wire.write(Daten[27]);
  }

  //Herstellerdaten
  if (Register == 0x23) {
    Wire.write(Daten[28]);
    Wire.write(Daten[29]);
  }

  //Herstellerinfo
  if (Register == 0x25) {
    Wire.write(Daten[30]);
    Wire.write(Daten[31]);
  }

  //Gerätetyp
  if (Register == 0x21) {
    Wire.write(Daten[32]);
    Wire.write(Daten[33]);
  }

  //Chemie
  if (Register == 0x22) {
    Wire.write(Daten[34]);
    Wire.write(Daten[35]);
  }

  //Spezifikationsinformation
  if (Register == 0x1A) {
    Wire.write(Daten[36]);
    Wire.write(Daten[37]);
  }

  //Zeit bis vollgeladen
  if (Register == 0x13) {
    Wire.write(Daten[38]);
    Wire.write(Daten[39]);
  }

  //Spannung Zelle 1
  if (Register == 0x3F) {
    Wire.write(Daten[40]);
    Wire.write(Daten[41]);
  }

  //Spannung Zelle 2
  if (Register == 0x3E) {
    Wire.write(Daten[42]);
    Wire.write(Daten[43]);
  }

  //Spannung Zelle 3
  if (Register == 0x3D) {
    Wire.write(Daten[44]);
    Wire.write(Daten[45]);
  }

  //Spannung Zelle 4
  if (Register == 0x3C) {
    Wire.write(Daten[46]);
    Wire.write(Daten[47]);
  }

  //state of health
  if (Register == 0x4F) {
    Wire.write(Daten[48]);
    Wire.write(Daten[49]);
  }

  //Batteriemodus
  if (Register == 0x03) {
    Wire.write(Daten[50]);
    Wire.write(Daten[51]);
  }

  //Ladestrom
  if (Register == 0x14) {
    Wire.write(Daten[52]);
    Wire.write(Daten[53]);
  }

  //Ladespannung
  if (Register == 0x15) {
    Wire.write(Daten[54]);
    Wire.write(Daten[55]);
  }

  //Stromregister
  if (Register == 0x2A) {
    Wire.write(Daten[56]);
    Wire.write(Daten[57]);
  }

}

void receiveEvent(int howMany) {
    Register = Wire.read();
}
Attachments
sniffer_output_correct.PNG
sniffer_output_correct.PNG (31.7 KiB) Viewed 2933 times
sniffer_output_stm32.PNG
sniffer_output_stm32.PNG (31.61 KiB) Viewed 2933 times
Last edited by TiMeX on Thu Jul 30, 2020 8:31 am, edited 1 time in total.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: I2C Problems with Nucleo 64 F103RB

Post by stevestrong »

viewtopic.php?f=2&t=301
Which core do you use?
TiMeX
Posts: 2
Joined: Thu Jul 30, 2020 7:30 am

Re: I2C Problems with Nucleo 64 F103RB

Post by TiMeX »

I am using the official STM32duino Core from here https://github.com/stm32duino/Arduino_Core_STM32
Post Reply

Return to “General discussion”