Amega328P and STM32F103C8t6 comunication I2C

Hi all,

I've come to your forum in the hope of finding help for a small problem I'm having. A problem that seems simple but is starting to drive me crazy (I've been looking for a solution for over a week).

I'm trying to explain it to you in the simplest way possible.

I have two cards, one is Atmega328P BLE and the other is STM32F103C8T6.

My first card (Atmega328P BLE) gets information from a sensor. It sends it to me via Bluetooth to my phone and it works fine. The small problem is that I would like this card to send the same information to the second card (the STM32F103C8T6), and I am having trouble setting up the I2C system.

My second board (STM32F103C8T6) needs to get a variable (the result of my probe on the Atmega328P BLE board) to make calculations.

My goal is to get the value of the 'eContent' variable in this code (which works perfectly), here is the code for the atmega328p BLE:

#include <Wire.h>
#define A1 1
#define SENSOR_PIN 10
bool featurePWMout = 1, featureAnalogInA1 = 0;
int eContentSkew = 50, refreshDelay = 0, eContentOverride = 0, voltOUTRange = 0;
unsigned int counttick = 0;

void setup() {
  Serial.begin(9600);
  if (featurePWMout) {
    TCCR1B = TCCR1B & 0b11111000 | 0x01;
    int analogOut = 255 * (0.1 / 5.0);
  }
}
void loop() {
  unsigned long highTime = pulseIn(SENSOR_PIN, HIGH);
  unsigned long lowTime = pulseIn(SENSOR_PIN, LOW);
  unsigned long pulsetime = highTime + lowTime;
  float VInA1;
  int AverageVoltagebitsA1;
  int AltA1;
  if (featureAnalogInA1) {
    AverageVoltagebitsA1 = 0;
    int MeasurementsToAverage = 16;
    for (int i = 0; i < MeasurementsToAverage; ++i) {
      AverageVoltagebitsA1 += MeasureVoltage();
      delay(1);
    }
    AverageVoltagebitsA1 /= MeasurementsToAverage;
    VInA1 = AverageVoltagebitsA1 * (5.0 / 1023.0);
  } else {
    VInA1 = 0.0;
  }
  if (pulsetime > 20100 || pulsetime < 6400) {
    if (counttick >= 2) {
      if (voltOUTRange) {
        if (pulsetime == 0) {
          if (featurePWMout) {
            int analogOut = 255 * (0.1 / 5.0);
          }
        }
        if (pulsetime >= 20100) {
          if (featurePWMout) {
            int analogOut = 255 * (4.8 / 5.0);
          }
        }
        if ((pulsetime <= 6400) && (pulsetime >= 1)) {
          if (featurePWMout) {
            int analogOut = 255 * (4.9 / 5.0);
          }
        }
      }
      Serial.print("[");
      Serial.print("=");
      Serial.print(pulsetime);
      Serial.print(",");
      Serial.print("-,");
      Serial.print("-,");
      Serial.print(",");
      Serial.print(VInA1, 1);
      Serial.print("]");
    } else if (counttick < 2) {
      counttick++;
    }
    return;
  }
  long eContent = int((1000000 / pulsetime) - eContentSkew);
  if (eContentOverride) {
    eContent = eContentOverride;
  }
  if (eContent < 0) {
    eContent = 0;
  } else if (eContent > 100) {
    eContent = 100;
  }
  float frequency = float(1000000 / pulsetime);
  float dutyCycle = 100 * (highTime / float(lowTime + highTime));
  float totalTime = float(1.0 / frequency);
  float period = float(100 - dutyCycle) * totalTime;
  int temperature = 40.25 * 10 * period - 81.25;
  int temperatureF = temperature * 1.8 + 32;

  if (temperatureF < -39 || temperatureF > 250) {
    return;
  }
  float desiredVoltage;
  if (voltOUTRange) {
    desiredVoltage = mapf(eContent, 0, 100, 0.5, 4.5);
  } else {
    desiredVoltage = mapf(eContent, 0, 100, 0, 5);
  }
  if (featurePWMout) {
    int analogOut = 255 * (desiredVoltage / 5.0);
  }
  Serial.print("[");
  Serial.print(temperature);
  Serial.print(",");
  Serial.print(eContent);
  Serial.print(",");
  Serial.print(desiredVoltage, 1);
  Serial.print(",");
  Serial.print(",");
  Serial.print(VInA1, 1);
  Serial.print("]");
  delay(refreshDelay);
  counttick = 0;
}
double mapf(double x, double in_min, double in_max, double out_min, double out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
int MeasureVoltage() {
  int rawbitsA1 = analogRead(A1);
  return rawbitsA1;
}

And to get the value of the variable 'econtent' in this code to use it (STM32F103C8T6 code)

boolean injection1 = false, injection2 = false, reception = false, ColdStart = false, FivemStart = false;
unsigned long time_cyl1 = 0UL, time_cyl2 = 0UL, time_E85_cyl1 = 0UL, time_E85_cyl2 = 0UL, watchdog1 = 0UL, watchdog2 = 0UL, RunTimeEngine = 0UL, AckRept = 0UL;

int P_ETH = 0; /// P_ETH is the result of econtent from atmega328P
int TempAmb;
int percent_prolongation = 0;

#include <Thermistor.h>
#include <NTC_Thermistor.h>

#define SENSOR_PIN             PA0
#define REFERENCE_RESISTANCE   10458
#define NOMINAL_RESISTANCE     11470
#define NOMINAL_TEMPERATURE    22.3
#define B_VALUE                3950
#define STM32_ANALOG_RESOLUTION 4095

Thermistor* thermistor;

void setup() {
  disableDebugPorts(); 
  pinMode(PB12, INPUT);                                           
  pinMode(PB13, INPUT);                                           

  pinMode(PB14, OUTPUT);                                          
  pinMode(PB4, OUTPUT);                                           
  pinMode(PB8, OUTPUT);                                           
  pinMode(PB9, OUTPUT);                                           

  digitalWrite(PB14, HIGH);
  digitalWrite(PB4, HIGH);

  attachInterrupt(PB12, Injection_Cyl_1, CHANGE);                    
  attachInterrupt(PB13, Injection_Cyl_2, CHANGE);                    
  Serial.begin(19200);

  thermistor = new NTC_Thermistor(
    SENSOR_PIN,
    REFERENCE_RESISTANCE,
    NOMINAL_RESISTANCE,
    NOMINAL_TEMPERATURE,
    B_VALUE,
    STM32_ANALOG_RESOLUTION 
  );

  TempAmb = int(thermistor->readCelsius());
  if (TempAmb < 10) {
    ColdStart = true;
    digitalWrite(PB4, LOW);
  }
  RunTimeEngine = millis();
}

void loop() {

  //if (Serial.available()) {the code to put for the I2C communication and for the Econtend variable to give a value to P_ETH !?!!!?!!}

  if (millis() < (AckRept + 5000UL)) {
    digitalWrite(PB14, LOW);
  } else digitalWrite(PB14, HIGH);

  if ((millis() > (RunTimeEngine + 30000UL )) && (FivemStart == false)) {
    Calculate_P_ETH();
    FivemStart = true;
  }

  if (injection1 == true) {
    injection1 = false;
    while (time_E85_cyl1 > micros());
    digitalWrite(PB9, LOW);
  }
  if (injection2 == true) {
    injection2 = false;
    while (time_E85_cyl2 > micros());
    digitalWrite(PB8, LOW);
  }

  if (watchdog1 < micros()) {
    digitalWrite(PB9, LOW);
    injection1 = false;
  }

  if (watchdog2 < micros()) {
    digitalWrite(PB8, LOW);
    injection2 = false;
  }
}

void Calculate_P_ETH() {
  P_ETH = constrain(P_ETH, 10, 85);
  if ((millis() < (RunTimeEngine + 30000UL )) && (ColdStart == true)) percent_prolongation = (((8 * P_ETH) / 10) - 8); 
  else percent_prolongation = (((34 * P_ETH) - 430) / 75); 
}

void Injection_Cyl_1() {
  noInterrupts();
  if (digitalRead(PB12) == HIGH) { 
    time_cyl1 = micros() - time_cyl1; // injection Time elpased in microseconds
    time_E85_cyl1 = (micros() + ((time_cyl1 * percent_prolongation) / 100)); 
    injection1 = true; // Flag for the end of injection traitement.
  }
  else {
    watchdog1 = micros() + 1000000UL;
    time_cyl1 = micros(); 
    injection1 = false;
    digitalWrite(PB9, HIGH);
  }
  interrupts();
}

void Injection_Cyl_2() {
  noInterrupts();
  if (digitalRead(PB13) == HIGH) {
    time_cyl2 = micros() - time_cyl2;
    time_E85_cyl2 = (micros() + ((time_cyl2 * percent_prolongation) / 100));
    injection2 = true;
  }
  else {
    watchdog2 = micros() + 1000000UL;
    time_cyl2 = micros();
    injection2 = false;
    digitalWrite(PB8, HIGH);
  }
  interrupts();
}

Thank you in advance for your valuable help,

Julie.

At first glance from what you've said, Bluetooth is working on your 328p. I don't know if Bluetooth can transmit (broadcast) to 2 different devices. I thought it was a 1-to-1 pairing, but I could be wrong.

Thank you markd833 for your reply,

I'm not looking to have the 2 cards communicate via Bluetooth. The Atmega328P BLE card sends to my phone the information, but I want to link the two cards so that the atmega card can also give the same information. I am looking for a wired connection between the two cards, that is what I want.

Thank you,

Julie

Ah, my mistake! I saw BLE several times and missed the reference to I2C in your original post. I think you can setup your STM32 to use the Arduino IDE. If that's the case, then I think the standard tutorials on I2C master (328p) and slave (STM32) should work.

I would have a read of the I2C section of Nick Gammons website. It's geared towards an Arduino UNO (328p), but it has simple examples of I2C master and slave code that you could try just to establish the basics.

The term "I2C" is in the title, but I don't see any I2C functions used in the sketch.
Do you want Serial communication ?
The ATmega328P has only one hardware serial port and it is used for the Serial Monitor.
Some use a software serial library to create a serial port, but those need almost the complete ATmega, there is not much else that can be done.

The I2C bus is not the best solution to communicate between processors. I don't know if the STM32 can work as a Slave (or call it "Target").