ESP32 Reciever

 avatar
unknown
csharp
2 days ago
6.8 kB
10
Indexable
// ============================================================
// XIAO C6 #2 — Receiver Hub
// Board: Seeed XIAO ESP32-C6
// MAC: 58:E6:C5:00:94:CC
//
// Receives from:
//   - XIAO C6 #1  (INA228 @ 0x40 = Solar1, 0x41 = Solar2)
//   - XIAO C6 #3  (ESC PWM + VESC telemetry, source = 1)
//   - XIAO C6 #4  (HX711 thrust only, source = 2)
// Sends:
//   - CSV: prefixed 18-value string over USB Serial to LabVIEW
//   - Throttle/ESTOP commands to ESC board via ESP-NOW
//
// CSV Format (18 values):
//   0  Solar1_V
//   1  Solar1_A
//   2  Solar1_W
//   3  Solar2_V
//   4  Solar2_A
//   5  Solar2_W
//   6  Battery_V  (0.0 not used)
//   7  Battery_A  (0.0 not used)
//   8  Battery_W  (0.0 not used)
//   9  Thrust_kg
//   10 Throttle_%
//   11 RPM
//   12 Motor_V
//   13 Motor_A
//   14 Motor_W
//   15 Motor_Temp_C
//   16 PWM_us
//   17 INA_Die_Temp_C
// ============================================================

#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>

// ---- ESC Board MAC (XIAO C6 #3) ----
uint8_t escBoardMAC[] = {0x58, 0xE6, 0xC5, 0x01, 0x8D, 0x38};

// ---- INA228 Packet ----
typedef struct __attribute__((packed)) {
  uint8_t  addr7;
  uint32_t ms;
  uint32_t errorMask;
  uint16_t config;
  uint16_t adc_config;
  uint16_t shunt_cal;
  uint16_t shunt_tempco;
  int32_t  vshunt24;
  int32_t  vbus24;
  int16_t  dietemp16;
  int32_t  current24;
  uint32_t power24;
  uint64_t energy40;
  int64_t  charge40;
  uint16_t diag_alrt;
  uint16_t sovl;
  uint16_t suvl;
  uint16_t bovl;
  uint16_t buvl;
  uint16_t temp_limit;
  uint16_t pwr_limit;
  uint16_t manufacturer_id;
  uint16_t device_id;
} InaPacket;

// ---- ESC Board Packet (source = 1) ----
typedef struct __attribute__((packed)) {
  uint8_t  source;
  float    throttle_pct;
  uint32_t pwm_us;
  float    rpm;
  float    motor_voltage;
  float    motor_current;
  float    motor_power;
  float    motor_temp;
  bool     vesc_valid;
} EscPacket;

// ---- HX711 Board Packet (source = 2) ----
typedef struct __attribute__((packed)) {
  uint8_t source;
  float   thrust_kg;
} HX711Packet;

// ---- Command Packet to ESC board ----
typedef struct __attribute__((packed)) {
  uint8_t source;
  float   throttle_pct;
  uint8_t estop;
} CommandPacket;

// ---- INA228 Conversion (0.005 ohm shunt) ----
#define VBUS_LSB     195.3125e-6f
#define CURRENT_LSB  (1.0f / (819.2e6f * 0.005f))
#define POWER_LSB    (3.2f * CURRENT_LSB)
#define TEMP_LSB     7.8125e-3f

// ---- Data Storage ----
struct PowerData {
  float voltage_V;
  float current_A;
  float power_W;
  float temp_C;
  bool  valid;
};

PowerData ina0 = {0};
PowerData ina1 = {0};

struct EscData {
  float    throttle_pct;
  uint32_t pwm_us;
  float    rpm;
  float    motor_voltage;
  float    motor_current;
  float    motor_power;
  float    motor_temp;
  bool     vesc_valid;
  bool     valid;
};

EscData escData = {0};
float thrustKg = 0.0;

// ---- E-stop state ----
bool  estopActive     = false;
float lastThrottleCmd = 0.0;

// ---- Non-blocking serial buffer ----
String serialBuffer = "";

// ---- ESP-NOW peer ----
esp_now_peer_info_t escPeer;

// ---- Decode INA228 ----
PowerData decodeINA(const InaPacket &p) {
  PowerData d;
  d.voltage_V = p.vbus24    * VBUS_LSB;
  d.current_A = p.current24 * CURRENT_LSB;
  d.power_W   = p.power24   * POWER_LSB;
  d.temp_C    = p.dietemp16 * TEMP_LSB;
  d.valid     = (p.errorMask == 0);
  return d;
}

// ---- Receive Callback ----
void onDataReceived(const esp_now_recv_info *recvInfo, const uint8_t *data, int len) {

  // INA228 from XIAO #1
  if (len == sizeof(InaPacket)) {
    InaPacket pkt;
    memcpy(&pkt, data, sizeof(pkt));
    if (pkt.addr7 == 0x40)      ina0 = decodeINA(pkt);
    else if (pkt.addr7 == 0x41) ina1 = decodeINA(pkt);
    return;
  }

  // ESC board data
  if (len == sizeof(EscPacket)) {
    EscPacket pkt;
    memcpy(&pkt, data, sizeof(pkt));
    if (pkt.source == 1) {
      escData.throttle_pct  = pkt.throttle_pct;
      escData.pwm_us        = pkt.pwm_us;
      escData.rpm           = pkt.rpm;
      escData.motor_voltage = pkt.motor_voltage;
      escData.motor_current = pkt.motor_current;
      escData.motor_power   = pkt.motor_power;
      escData.motor_temp    = pkt.motor_temp;
      escData.vesc_valid    = pkt.vesc_valid;
      escData.valid         = true;
    }
    return;
  }

  // HX711 thrust data
  if (len == sizeof(HX711Packet)) {
    HX711Packet pkt;
    memcpy(&pkt, data, sizeof(pkt));
    if (pkt.source == 2) {
      thrustKg = pkt.thrust_kg;
    }
    return;
  }
}

// ---- Send command to ESC board ----
void sendCommand(float throttle, bool estop) {
  CommandPacket cmd;
  cmd.source       = 10;
  cmd.throttle_pct = throttle;
  cmd.estop        = estop ? 1 : 0;
  esp_now_send(escBoardMAC, (uint8_t *)&cmd, sizeof(cmd));
}

// ---- Non-blocking serial command parser ----
void checkSerialCommands() {
  while (Serial.available()) {
    char c = Serial.read();
    if (c == '\n') {
      serialBuffer.trim();
      if (serialBuffer == "ESTOP") {
        estopActive     = true;
        lastThrottleCmd = 0.0;
        sendCommand(0.0, true);
      } else if (serialBuffer.startsWith("CMD:")) {
        float throttle  = constrain(serialBuffer.substring(4).toFloat(), 0.0, 100.0);
        estopActive     = false;
        lastThrottleCmd = throttle;
        sendCommand(throttle, false);
      }
      serialBuffer = "";
    } else if (c != '\r') {
      serialBuffer += c;
    }
  }
}

void setup() {
  Serial.begin(115200);
  delay(200);

  // ESP-NOW with legacy protocol for C6 compatibility
  WiFi.mode(WIFI_STA);
  esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N);
  esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE);

  if (esp_now_init() != ESP_OK) {
    while (true) delay(1000);
  }

  esp_now_register_recv_cb(onDataReceived);

  memcpy(escPeer.peer_addr, escBoardMAC, 6);
  escPeer.channel = 1;
  escPeer.encrypt = false;
  esp_now_add_peer(&escPeer);
}

void loop() {
  checkSerialCommands();

  // Send 18-value CSV to LabVIEW
  Serial.printf("CSV:"
    "%.4f,%.4f,%.4f,"
    "%.4f,%.4f,%.4f,"
    "%.4f,%.4f,%.4f,"
    "%.3f,"
    "%.1f,"
    "%.0f,"
    "%.3f,%.3f,%.3f,"
    "%.1f,"
    "%lu,"
    "%.2f\n",
    ina0.voltage_V, ina0.current_A, ina0.power_W,
    ina1.voltage_V, ina1.current_A, ina1.power_W,
    0.0, 0.0, 0.0,
    thrustKg,
    escData.throttle_pct,
    escData.rpm,
    escData.motor_voltage, escData.motor_current, escData.motor_power,
    escData.motor_temp,
    escData.pwm_us,
    ina0.temp_C
  );

  delay(20);
}
Editor is loading...
Leave a Comment