🤖Have you ever tried Chat.M5Stack.com before asking??😎
    M5Stack Community
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Register
    • Login

    Pa.HUB: use any port for connection.

    General
    3
    9
    1.2k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      Surya
      last edited by

      I have a working script that reads and displays temperature data from the SHT30 and SHT40 sensors. Both sensors are connected to the AtomS3 through Pa.HUB because they share the same I2C address.

      Here is my setup:
      6252c4c7-e020-4940-b83a-ae8f03537f0f-image.png

      As shown in the picture, if I connect the sensors to a specific port in the hub, I can retrieve readings from them. However, I want both sensors to work on any port I plug them into. I have been continuously trying to modify the script to achieve this, but all attempts have failed.

      Here is my failing script:

      #include <M5AtomS3.h>
      #include <M5Unified.h>
      #include <SPI.h>
      #include <SSLClient.h>
      #include <M5_Ethernet.h>
      #include <PubSubClient.h>
      #include "certificates.h"
      #include <ArduinoJson.h>
      #include <SensirionI2CSht4x.h>
      #include "M5UnitENV.h"
      
      // Header files that contain the icons
      #include "air.h"
      #include "liquid.h"
      #include "thermometer.h"
      
      #define SCK 5
      #define MISO 7
      #define MOSI 8
      #define CS 6
      
      SHT3X sht3x;
      SensirionI2cSht4x sht4x;
      
      float temperature, pressure, humidity, liquid_temperature;
      uint16_t error;
      char errorMessage[256];
      
      // The MQTT topics that this device should publish/subscribe
      #define AWS_IOT_PUBLISH_TOPIC "AtomS3/env"
      #define AWS_IOT_SUBSCRIBE_TOPIC "AtomS3/msg"
      
      const char my_cert[] = "-----BEGIN CERTIFICATE-----\n"
                             "MIIDxxxx...\n"
                             "-----END CERTIFICATE-----\n";
      const char my_key[] = "-----BEGIN RSA PRIVATE KEY-----\n"
                            "MIIExxxx...\n"
                            "-----END RSA PRIVATE KEY-----\n";
      
      SSLClientParameters mTLS = SSLClientParameters::fromPEM(my_cert, sizeof my_cert, my_key, sizeof my_key);
      
      byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x89};
      
      const char *mqttServer = "a1xxxx....amazonaws.com";
      
      void callback(char *topic, byte *payload, unsigned int length)
      {
          Serial.print("Message arrived [");
          Serial.print(topic);
          Serial.print("] ");
          for (int i = 0; i < length; i++)
          {
              Serial.print((char)payload[i]);
          }
          Serial.println();
      }
      
      EthernetClient ethClient;
      SSLClient ethClientSSL(ethClient, TAs, (size_t)TAs_NUM, GPIO_NUM_10);
      PubSubClient client(mqttServer, 8883, callback, ethClientSSL);
      
      void reconnect()
      {
          // Loop until we're reconnected
          while (!client.connected())
          {
              Serial.print("Attempting MQTT connection...");
              if (client.connect("arduinoClient"))
              {
                  Serial.println("connected");
                  client.subscribe("ENV_TEST");
              }
              else
              {
                  Serial.print("failed, rc=");
                  Serial.print(client.state());
                  Serial.println(" try again in 5 seconds");
                  delay(5000);
              }
          }
      }
      
      void publishMessage()
      {
          StaticJsonDocument<200> doc;
          doc["air-temperature"] = temperature;
          doc["air-humidity"] = humidity;
          doc["liquid-temperature"] = liquid_temperature;
          char jsonBuffer[512];
          serializeJson(doc, jsonBuffer);
      
          client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer);
      }
      
      void setup()
      {
          M5.begin();
          M5.Power.begin();
          M5.Lcd.setTextSize(2);
          M5.Lcd.println("Init..");
          SPI.begin(SCK, MISO, MOSI, -1);
          Wire.begin();
          Serial.begin(115200);
      
          for (uint8_t port = 1; port < 6; port++)
          {
              Wire.beginTransmission(0x70);
              Wire.write(port);
              Wire.endTransmission();
              delay(1000);
      
              if (sht3x.begin(&Wire, SHT3X_I2C_ADDR, 2, 1, 400000U))
              {
                  Serial.print("SHT3X sensor found on port ");
                  Serial.println(port);
              }
      
              sht4x.begin(Wire, SHT40_I2C_ADDR_44);
          }
      
      
          Ethernet.init(CS);
          M5.Lcd.println("Connecting ethernet...");
          while (Ethernet.begin(mac) != 1)
          {
              Serial.println("Error getting IP address via DHCP, trying again...");
              delay(1000);
          }
      
          // Check for Ethernet hardware present
          if (Ethernet.hardwareStatus() == EthernetNoHardware)
          {
              Serial.println(
                  "Ethernet shield was not found.  Sorry, can't run without "
                  "hardware. :(");
              while (true)
              {
                  delay(100);
              }
          }
          if (Ethernet.linkStatus() == LinkOFF)
          {
              Serial.println("Ethernet cable is not connected.");
          }
          delay(1000);
      
          ethClientSSL.setMutualAuthParams(mTLS);
          client.connect("ENV_TEST");
      }
      
      void loop()
      {
          temperature = humidity = pressure = liquid_temperature = NULL;
          if (!client.connected())
          {
              M5.Lcd.clear();
              M5.Lcd.setCursor(0, 0);
              M5.Lcd.println("reconnecting...");
              reconnect();
          }
          else
          {
              for (uint8_t port = 1; port < 6; port++)
              {
                  Wire.beginTransmission(0x70);
                  Wire.write(port);
                  Wire.endTransmission();
                  delay(500);
      
                  if (liquid_temperature == NULL)
                  {
                      if (sht3x.update())
                      {
                          liquid_temperature = sht3x.fTemp;
                          Serial.print("Temperature(L): ");
                          Serial.print(liquid_temperature);
                          Serial.print("\t");
                      }
                  }
      
                  if (temperature == NULL && humidity == NULL)
                  {
                      error = sht4x.measureHighPrecision(temperature, humidity);
                      if (!error)
                      {
                          Serial.print("Temperature(A):");
                          Serial.print(temperature);
                          Serial.print("\t");
                          Serial.print("Humidity:");
                          Serial.println(humidity);
                      } /**else {
                          errorToString(error, errorMessage, 256);
                          Serial.print("Error: ");
                          Serial.println(errorMessage);
                      }**/
                  }
              }
              // Celsius to Fahrenheit conversion
              if (temperature != 0)
              {
                  temperature = (temperature * 9 / 5) + 32;
              }
      
              M5.Lcd.clear();
              M5.Lcd.setSwapBytes(true);
              // Draw the icons
              M5.Lcd.pushImage(0, 0, airWidth, airHeight, air);
              M5.Lcd.pushImage(32, 0, thermometerWidth, thermometerHeight, thermometer);
              M5.Lcd.pushImage(0, 45, airWidth, airHeight, air);
              M5.Lcd.pushImage(32, 45, liquidWidth, liquidHeight, liquid);
              M5.Lcd.pushImage(0, 90, liquidWidth, liquidHeight, liquid);
              M5.Lcd.pushImage(32, 90, thermometerWidth, thermometerHeight, thermometer);
      
              M5.Lcd.setCursor(70, 10);
              if (temperature != 0)
              {
                  M5.Lcd.printf("%2.1f", temperature);
                  M5.Lcd.setTextSize(1);
                  M5.Lcd.print("o");
                  M5.Lcd.setTextSize(2);
              }
              else
              {
                  M5.Lcd.print("-");
              }
      
              M5.Lcd.setCursor(70, 55);
              if (humidity != 0)
              {
                  M5.Lcd.printf("%2.0f%%", humidity);
              }
              else
              {
                  M5.Lcd.print("-");
              }
      
              M5.Lcd.setCursor(70, 100);
              if (liquid_temperature != 0)
              {
                  M5.Lcd.printf("%2.1f", liquid_temperature);
                  M5.Lcd.setTextSize(1);
                  M5.Lcd.print("o");
                  M5.Lcd.setTextSize(2);
              }
              else
              {
                  M5.Lcd.print("-");
              }
      
              delay(100);
              publishMessage();
          }
          client.loop();
          delay(3000);
      }
      

      Can you guys help me with this? Any advice or alternative approach would be greatly appreciated.

      ajb2k3A 1 Reply Last reply Reply Quote 0
      • ajb2k3A
        ajb2k3 @Surya
        last edited by

        @Surya they have to be connected to the lowest free number port for some reason

        UIFlow, so easy an adult can learn it!
        If I don't know it, be patient!
        I've ether not learned it or am too drunk to remember it!
        Author of the WIP UIFlow Handbook!
        M5Black, Go, Stick, Core2, and so much more it cant be fit in here!

        S 1 Reply Last reply Reply Quote 0
        • S
          Surya @ajb2k3
          last edited by

          @ajb2k3 Thanks for your prompt response.
          If so, is there any way to detect which sensor is connected to which port? (Basically, I don't want a sensor to be statically assigned to a specific port)
          This way, I can detect the sensor port and get the temperature data using an appropriate command.

          felmueF 1 Reply Last reply Reply Quote 0
          • felmueF
            felmue @Surya
            last edited by felmue

            Hello @Surya

            I think you might be selecting the channels/ports incorrectly. If you have a look at the datasheet - section 8.5.4 Control Register - you see that each channel/port is one bit of the control register byte.

            E.g. your for loop going from 1 to 5 actually selects channel/port 1, 2, 1+2, 3, 1+3, 2+3. Not exactly what you want.

            BTW: you can also see how the channels/ports are selected in the Adafruit library here.

            Thanks
            Felix

            GPIO translation table M5Stack / M5Core2
            Information about various M5Stack products.
            Code examples

            S 1 Reply Last reply Reply Quote 0
            • S
              Surya @felmue
              last edited by

              Hello @felmue
              I'll investigate and give it a try. Thank you!

              1 Reply Last reply Reply Quote 0
              • S
                Surya
                last edited by

                void initializeSensors()
                {
                    for (int port = 0; port < 6; port++)
                    {
                        Wire.beginTransmission(0x70);
                        Wire.write(1 << port);
                        Wire.endTransmission();
                        delay(10);
                
                        Wire.beginTransmission(SHT40_I2C_ADDR_44);
                        if (Wire.endTransmission() == 0)
                        {
                            float temp, hum;
                            sht4x.begin(Wire, SHT40_I2C_ADDR_44);
                            uint16_t error = sht4x.measureHighPrecision(temp, hum);
                            if (error == 0)
                            {
                                sht4xPort = port;
                                sht4x.begin(Wire, SHT40_I2C_ADDR_44);
                                Serial.print("SHT4X found on port ");
                                Serial.println(port);
                                continue;
                            }
                        }
                    }
                
                    for (int port = 0; port < 6; port++)
                    {
                        if (port == sht4xPort)
                        {
                            continue;
                        }
                        Wire.beginTransmission(0x70);
                        Wire.write(1 << port);
                        Wire.endTransmission();
                        delay(10);
                
                        Wire.beginTransmission(SHT3X_I2C_ADDR);
                        if (Wire.endTransmission() == 0)
                        {
                            // Try to read a unique characteristic of SHT3X
                            if (sht3x.begin(&Wire, SHT3X_I2C_ADDR, 2, 1, 400000U))
                            {
                                sht3xPort = port;
                                Serial.print("SHT3X found on port ");
                                Serial.println(port);
                                continue;
                            }
                        }
                    }
                }
                
                void setup()
                {
                    M5.begin();
                    M5.Power.begin(); // Init power
                    M5.Lcd.setTextSize(2);
                    M5.Lcd.println("Init..");
                    SPI.begin(SCK, MISO, MOSI, -1);
                    Wire.begin();
                    Serial.begin(115200);
                    delay(3000);
                
                    initializeSensors();
                
                    Ethernet.init(CS);
                    M5.Lcd.println("Connecting ethernet...");
                    while (Ethernet.begin(mac) != 1)
                    {
                        Serial.println("Error getting IP address via DHCP, trying again...");
                        delay(1000);
                    }
                
                    // Check for Ethernet hardware present
                    if (Ethernet.hardwareStatus() == EthernetNoHardware)
                    {
                        Serial.println(
                            "Ethernet shield was not found.  Sorry, can't run without "
                            "hardware. :(");
                        while (true)
                        {
                            delay(100);
                        }
                    }
                    if (Ethernet.linkStatus() == LinkOFF)
                    {
                        Serial.println("Ethernet cable is not connected.");
                    }
                    delay(1000);
                
                    ethClientSSL.setMutualAuthParams(mTLS);
                    client.connect("ENV_TEST");
                }
                
                void loop()
                {
                    temperature = humidity = pressure = liquid_temperature = 0;
                    if (!client.connected())
                    {
                        M5.Lcd.clear();
                        M5.Lcd.setCursor(0, 0);
                        M5.Lcd.println("reconnecting...");
                        reconnect();
                    }
                    else
                    {
                        uint16_t error;
                        char errorMessage[256];
                
                        Serial.println(sht3xPort);
                        Serial.println(sht4xPort);
                        if (sht3xPort != -1)
                        {
                            Wire.beginTransmission(0x70);
                            Wire.write(1 << sht3xPort);
                            Wire.endTransmission();
                            delay(10);
                            if (sht3x.update())
                            {
                                liquid_temperature = sht3x.fTemp;
                                Serial.print("Temperature(L): ");
                                Serial.print(liquid_temperature);
                                Serial.print("\t");
                            }
                        }
                
                        if (sht4xPort != -1)
                        {
                            Wire.beginTransmission(0x70);
                            Wire.write(1 << sht4xPort);
                            Wire.endTransmission();
                            delay(10);
                            uint16_t error = sht4x.measureHighPrecision(temperature, humidity);
                
                            if (error)
                            {
                                char errorMessage[256];
                                errorToString(error, errorMessage, 256);
                                Serial.print("Error: ");
                                Serial.println(errorMessage);
                            }
                            else
                            {
                                Serial.print("Temperature(A): ");
                                Serial.print(temperature);
                                Serial.print("\tHumidity: ");
                                Serial.println(humidity);
                            }
                
                            // Convert Celsius to Fahrenheit
                            if (temperature != 0)
                            {
                                temperature = (temperature * 9 / 5) + 32;
                            }
                        }
                
                        M5.Lcd.clear();
                        // Swap the colour byte order when rendering
                        M5.Lcd.setSwapBytes(true);
                        // Draw the icons
                        M5.Lcd.pushImage(0, 0, airWidth, airHeight, air);
                        M5.Lcd.pushImage(32, 0, thermometerWidth, thermometerHeight, thermometer);
                        M5.Lcd.pushImage(0, 45, airWidth, airHeight, air);
                        M5.Lcd.pushImage(32, 45, liquidWidth, liquidHeight, liquid);
                        M5.Lcd.pushImage(0, 90, liquidWidth, liquidHeight, liquid);
                        M5.Lcd.pushImage(32, 90, thermometerWidth, thermometerHeight, thermometer);
                
                        M5.Lcd.setCursor(70, 10);
                        if (temperature != 0)
                        {
                            M5.Lcd.printf("%2.1f", temperature);
                            M5.Lcd.setTextSize(1);
                            M5.Lcd.print("o");
                            M5.Lcd.setTextSize(2);
                        }
                        else
                        {
                            M5.Lcd.print("-");
                        }
                
                        M5.Lcd.setCursor(70, 55);
                        if (humidity != 0)
                        {
                            M5.Lcd.printf("%2.0f%%", humidity);
                        }
                        else
                        {
                            M5.Lcd.print("-");
                        }
                
                        M5.Lcd.setCursor(70, 100);
                        if (liquid_temperature != 0)
                        {
                            M5.Lcd.printf("%2.1f", liquid_temperature);
                            M5.Lcd.setTextSize(1);
                            M5.Lcd.print("o");
                            M5.Lcd.setTextSize(2);
                        }
                        else
                        {
                            M5.Lcd.print("-");
                        }
                
                        delay(100);
                        publishMessage();
                    }
                    client.loop();
                    delay(3000);
                }
                

                This script collects sensor data wherever I connect it to the hub. However, I'm facing an issue: when I first connect it to the power supply, it works fine, but if I press the reset button on the AtomS3, I get this error: "[Wire.cpp:513] requestFrom(): i2cRead returned Error 263."

                I found that this error is caused by the SHT3X sensor. When this happens, unplugging and re-plugging the sensor and then pressing the reset button makes it work again. I suspect that pressing the reset button breaks the loop without properly resetting the SHT3X sensor.

                I'm looking for a way to reset the SHT3X sensor before reinitializing it but haven't found a solution. Please help me with this.

                S 1 Reply Last reply Reply Quote 0
                • S
                  Surya @Surya
                  last edited by

                  45c6aa4d-0e53-4863-b57b-a00ce26aa9cc-image.png

                  1 Reply Last reply Reply Quote 0
                  • S
                    Surya
                    last edited by

                    Unplugging and replugging the power supply also fixes the issue. Do you guys know how to programmatically restart the AtomS3, I2C bus, or sensor?

                    1 Reply Last reply Reply Quote 0
                    • S
                      Surya
                      last edited by

                      Here are some additional details:

                      When I initially scan for the I2C bus, it says:
                      Scanning...
                      I2C device found at address 0x70

                      After pressing the reset button in AtomS3, it says:
                      Scanning...
                      I2C device found at address 0x44
                      I2C device found at address 0x70
                      I2C device found at address 0x76

                      I tried using Wire.end() to end all I2C communication, but the addresses still remains open. How to close them?

                      void scanI2CBus()
                      {
                          byte error, address;
                      
                          Serial.println("Scanning...");
                      
                          for (address = 1; address < 127; address++)
                          {
                              // The I2C address 0x00 is reserved and the addresses should be between 0x01 and 0x7F
                              Wire.beginTransmission(address);
                              error = Wire.endTransmission();
                      
                              if (error == 0)
                              {
                                  Serial.print("I2C device found at address 0x");
                                  if (address < 16)
                                  {
                                      Serial.print("0");
                                  }
                                  Serial.print(address, HEX);
                              }
                          }
                      }
                      
                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post