Sending data that I read over i2c to Serial port using Arduino + Microcontroller

Hello! Apologies if this is the wrong category, first time

In the last few days I've been trying to figure out an issue with my code, here's some background and then an explanation of the problem:

Master: Arduino Uno
Slave: 0x50 (a custom microcontroller MVLD)
Here's a diagram explaining how it is all connected:

connection_diagram

Background:
Trying to read Temperature from a custom sensor that's connected to the MVLD - I have a device that sits on the i2c bus, and can monitor it, so if I write to the i2c bus it can detect it, if I read from it it'll also detect it (aardvark i2c), I'm using a python code in order to communicate with the serial port (using PySerial), and then I send the data from the serial port to the i2c bus using the arduino code, for example if I wanted to set the current I can do that using the python code and it works. The issue is when I try to read, it just won't send the bytes that I am reading to the Serial port so I could later print it out in my python code (I know I am reading it because of the i2c monitor device, and it is working)
Not sure if I gave a clear enough explanation, but TLDR: I'm accessing data on the microcontroller (MVLD) using the i2c bus, and I'm trying to print out what I'm reading to the serial port, so I can then read it in my python code.

Arduino code:

#include <Wire.h>

void setup() {

  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(SCL, INPUT_PULLUP);
  pinMode(SDA, INPUT_PULLUP);
  Serial.println("Arduino setup");
}

void loop() {

  unsigned char message[20];

  bool isRead = false;
  int mIdx = 0;
  if (Serial.available())
  {
    Serial.print("Arduino Received : ");
    //  int mIdx = 1;
    while (Serial.available())
    {

      message[mIdx] = Serial.read();

      Serial.print(message[mIdx]);
      Serial.print(" ");
      mIdx++;
      if ((mIdx == 1) && (message[0]) == 0x02)
      {
        isRead = true;
      }
      if (isRead && mIdx >= 3)
        break;
      delay(5);

    }

    message[mIdx] = '\0';

    Serial.println("Arduino " + message[0]);
    Serial.println("Arduino read");

    Wire.beginTransmission(0x50); // transmit to device #9
    Wire.write(message + 1, mIdx - 1);
    Wire.endTransmission();

    Wire.requestFrom(0x50, 3, true);
    while (Wire.available()) {
      byte readBytes = Wire.requestFrom(0x50, 3);
      Serial.print(readBytes, HEX);
      Serial.print(" ");
      delay(1000);

      // This while loop works, but it doesn't seem to be printing the bytes to the serial port, reading works
    }
    delay(100);
    if (Wire.available()) {
      while (Wire.available() <= 3) {
        delay(1);
      }
      Wire.readBytes(message, 3);
      delay(100);
      Serial.write(message, 3);
    }


    delay(100);


  }
  delay(100);
}

Python code that I use to access the temperature sensor, and then read the data from it:

    checksum = (slave_id + temperature_cmd_id) # Set the checksum for the Temperature
    write_structure = [enable_writing, temperature_cmd_id, checksum] # Create the write structure for the Temperature
    write_structure_bytearray = bytearray(write_structure) # Turn the write structure into bytes

    serial_instance.write(write_structure_bytearray) # Write the bytes to the serial port

    while True:
        for j in range(2):

            temperature_line = serial_instance.readline() # Read the data from the serial instance
            print(temperature_line.decode('utf').replace('Arduino led', '').strip()) # Decode data using 'utf' decode and remove unneccessary text

FYI I am a beginner with arduino and this is my first project, so please try and explain the answers in a tad bit more detail so I could understand them :slight_smile:

If I didn't give a clear enough explanation or there's something missing, please let me know so I can try and explain it properly!

Thanks!

Welcome to the forum.

Please give a description of the commands via the Serial port. Is there a Carriage Return or Line Feed as well ?

I'm sorry to say, but you may have to rewrite the sketch.

To read a Serial input, there are two options:

  1. Wait with a delay or wait with a function that waits until the full command has been received.
  2. Never wait, put any incoming data in a buffer. Process the buffer when the full command is in the buffer.

You have a mix of both, I can not guarantee that it will work.

That is not how to use the Wire library.
Would my alternative explanation of the functions of the Wire library help ?

Not quite sure what you mean by Carriage Return or Line Feed?

About the mix of both, the writing and reading seems to work well from and to the Serial port, just except this part, and I'm unsure why

If I have to rewrite the sketch I'm just not sure where to start as this sketch wasn't fully written by me, though thank you for the explanation! It does make things clearer

Please explain MLVD and TLDR, I am lost. Why not use the Arduino to read the temperature if that is all you want to do? Maybe send if over WiFi or Bluetooth if you do not want to run around with a wire all the time. From what I understand you initiate the MLVD with a python generated initiation message (these are bytes?) down to the Arduino I2C which forwards it? Why not store the initiation bytes on the Arduino? Then just ask Arduino to provide you with the temperature directly and send that back.

    Wire.requestFrom(0x50, 3, true);
    while (Wire.available()) {
      byte readBytes = Wire.requestFrom(0x50, 3);

After you request the bytes you need to pick them up right after and I think that would be the problem here. I do not think you can read the bytes directly to your message by calling:

 Wire.readBytes(message, 3);

You need to call Wire.read() immediately after you made the request. Use the read-out to get a temperature and put that back inside your message towards python. Delays in the I2C routine should mostly be avoided from what I know.

Wire.read()

I might be missing something as I have not used I2C for a while.

The MVLD is a microcontroller that's connected to a laser, the temperature sensor is built onto the laser, and I have to have the laser connected to the microcontroller, which is why it isn't connected to the arduino directly, and it doesn't have wifi and there isn't much of a reason to use wifi either

TLDR = Too Long Didn't Read (a short explanation of the message above)

Yes, that's what I'm doing, sending the data (bytes) through the Serial port from python to the arduino, from there I send the data to the i2c and then I read back from the i2c (in this case I'm reading the temperature), which does go through the i2c, but not back to the python code/serial it seems

If you could give an example of how I could do it, yeah that's probably the best option!

I've tried that and it still doesn't seem to be going back to python, or the other possible explanation is it isn't going to the serial port