Bluepill as I2C Master and Slave

Post here all questions related to STM32 core if you can't find a relevant section!
Post Reply
jenspogo
Posts: 30
Joined: Mon Feb 24, 2020 10:42 am

Bluepill as I2C Master and Slave

Post by jenspogo »

Hey everybody,
I'm playing around with a bluepill Board. The Idea is to create a few boards with STM32F103 Prozessors. These Boards shell collect data and do some other stuff. Sometimes a Raspberry will collect some data. (Sometimes in fact is 10ms ;) )
Currently i'm using a Raspberry pi 4 as an I2C Master and the Bluepill as a Slave on I2C2. Also a SCD30 Sensor from sensirion as an example on the I2C(1) Bus on the BluePill.
when the Bluepill collects data from the Sensor and exactly in this moment the Raspberry also sends a read request, the connection breaks down and the bluepill pulls the clock of the I2C2 Bus low (the one to the raspberry).

Are there maybe some Ideas?

I'm using the board manager files from github:
https://github.com/stm32duino/BoardMana ... index.json

my Arduino code is attached

Code: Select all

#include <Wire.h>

#include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30
SCD30 airSensor;


#define SLAVE_ADDRESS 0x08
#define DATA_TO_SEND_LENGHT 30

char number[30];
char test[DATA_TO_SEND_LENGHT];

//            SDA  SCL
TwoWire Wire2(PB11, PB10);

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  
  //Serial.begin(115200);
  //Serial.println("SCD30 Example");
  
  // initialize wire
  Wire.begin();
  Wire2.begin(SLAVE_ADDRESS);
  //Wire2.setClock(STM_I2C2_FREQ);
  Wire2.onReceive(receiveData2);
  Wire2.onRequest(sendData2);
  
  for (int i=0; i<DATA_TO_SEND_LENGHT ; i++){
  test[i]=95;
  }
  
    if (airSensor.begin() == false)
  {

        digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// Turn the LED from off to on, or on to off
        delay (200);
        digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// Turn the LED from off to on, or on to off
        delay (200);
    }
  }
  
  void loop()
{
  if (airSensor.dataAvailable())
  {
  digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// Turn the LED from off to on, or on to off
 	 f_CO2 = airSensor.getCO2();
 	 f_temp = airSensor.getTemperature();
 	 f_humidity = airSensor.getHumidity();
 	}
   delay(500);
   }
   
   // callback for received data
void receiveData2(int byteCount) {
  digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// Turn the LED from off to on, or on to off
  int i = 0;
  while (Wire.available()) {
   	number[i] = Wire.read();
    	i++;
 	}
  
}  // end while

// callback for sending data
void sendData2() {
 	 digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// Turn the LED from off to on, or on to off
  	Wire.write(test,sizeof(test));
}

to read out the data I use python SMBus

Code: Select all

#RPi Pinouts

#I2C Pins
#GPIO2 -> SDA
#GPIO3 -> SCL

#Import the Library Requreid
import smbus
import time

# for RPI version 1, use "bus = smbus.SMBus(0)"
bus = smbus.SMBus(1)
time.sleep(.1)
# This is the address we setup in the Arduino Program
#Slave Address 1
address = 0x08
read_length = 30

data = [255,255,0,1,2,3,4,5,6,7]
data_list = list(data)
count = 0


def writeNumber(value):    
    bus.write_i2c_block_data(address,0,value)
    return -1

def readNumber():

    number = bus.read_i2c_block_data(address, 0,read_length)
    return number

while True:
    state=1
    if int(state) == 1:
        for j in range (0,6):
           writeNumber(value)
            j +=1


        #print("READ all data")
        for i in range (0,6):
            x = readNumber()
            #time.sleep(.000005)
            i+=1
        #x_string = ''.join(chr(i) for i in x)
            #print(x_string)
            #time.sleep(.001)

    else:
        print ("enter valid function")

    count = count + 1
    print (count)

    time.sleep(.0005)


#End of the Script

User avatar
fpiSTM
Posts: 1756
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Bluepill as I2C Master and Slave

Post by fpiSTM »

jenspogo
Posts: 30
Joined: Mon Feb 24, 2020 10:42 am

Re: Bluepill as I2C Master and Slave

Post by jenspogo »

Hey :) thanks for your answer! with the updatet wire.h library it works most of the time.
Sometimes i do have a breakdown on the second i2c Bus. (attached picture)
i2c2_breakdown2.JPG
i2c2_breakdown2.JPG (82.55 KiB) Viewed 6414 times
Could be the reason, that I reuse the same variable to store the Sensor Variable and then send them away?

Is it possible to reset the Bus? I think i wrote somewhere that it is not possible...

my code:

Code: Select all

/*
  Reading CO2, humidity and temperature from the SCD30
  By: Nathan Seidle
  SparkFun Electronics
  Date: May 22nd, 2018
  License: MIT. See license file for more information but you can
  basically do whatever you want with this code.

  Feel like supporting open source hardware?
  Buy a board from SparkFun! https://www.sparkfun.com/products/15112

  This example prints the current CO2 level, relative humidity, and temperature in C.

  Hardware Connections:
  Attach RedBoard to computer using a USB cable.
  Connect SCD30 to RedBoard using Qwiic cable.
  Open Serial Monitor at 115200 baud.
*/

#include <Wire.h>

//#include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30
//SCD30 airSensor;


#define SLAVE_ADDRESS 0x08
#define DATA_TO_SEND_LENGHT 30
#define STM_I2C2_FREQ 400000


char number[30];
char test[DATA_TO_SEND_LENGHT];
char test2[DATA_TO_SEND_LENGHT];
int   state = 0;
float  f_CO2 = 0;
char  c_CO2_buffer[8];
float f_humidity=0;
char  c_humidity_buffer[8];
float f_temp=0;
char  c_temp_buffer[8];

//            SDA  SCL
TwoWire Wire2(PB11, PB10);


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  
  //Serial.begin(115200);
  //Serial.println("SCD30 Example");
  
  // initialize wire
  Wire.begin();
  Wire2.begin(SLAVE_ADDRESS);
  //Wire2.setClock(STM_I2C2_FREQ);
  Wire2.onReceive(receiveData2);
  Wire2.onRequest(sendData2);

  for (int i=0; i<DATA_TO_SEND_LENGHT ; i++){
  test[i]=95;
  }
  for (int i=0; i<DATA_TO_SEND_LENGHT ; i++){
  test2[i]=95;
  }
  test[0]='C';
  test[1]='O';
  test[2]='2';
  test[3]=':';
  test[10]='T';
  test[11]=':';
  test[18]='H';
  test[19]=':';

  // signal for correct initialization
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);  
  
  


}

void loop()
{
digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
  delay(1000);
}

// callback for received data
void receiveData2(int byteCount) {
  digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// Turn the LED from off to on, or on to off
  int i = 0;
  while (Wire2.available()) {
    number[i] = Wire2.read();
    i++;
  }
  number[i] = '\0';
  //Serial.print(number);
}  // end while

// callback for sending data
void sendData2() {
  digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// Turn the LED from off to on, or on to off
  Wire2.write(test2,sizeof(test2));
}



//End of the program
User avatar
fpiSTM
Posts: 1756
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Bluepill as I2C Master and Slave

Post by fpiSTM »

Hi
Fine. anyway they are several other fixes around I2C.
So, the best way is you use the master of the core or wait the next 1.9.0 release.

Ex:
https://github.com/stm32duino/Arduino_C ... 2/pull/888
Post Reply

Return to “General discussion”