You are here

Logging additional Sensors with the VESC on the Phone App

6 posts / 0 new
Last post
palm369
Offline
Last seen: 1 month 1 week ago
VESC Free
Joined: 2018-08-28 16:46
Posts: 4
Logging additional Sensors with the VESC on the Phone App

Hi, I need to log the force value of a load cell.

My Idea was to to read it with and Arduino and then send it to the VESC 75100 somehow.

As the VESC has the PPM input and its pretty easy to send out this from the Arduino, I was doing that. Now I notices that the VESC don't even log the PPM input value.

Is it in ANY way possible to have the data in the log file of the phone app? I also have a ESP32 and also a CAN Board for it. For example converting it to analog and reading an analog port of the VESC? I cannot find a way.

Thankful for suggestions!

palm369
Offline
Last seen: 1 month 1 week ago
VESC Free
Joined: 2018-08-28 16:46
Posts: 4

Anyone? I am pretty confident that there is a super simple way to do this. Can somebody please point me in the right direction?

electricfox
electricfox's picture
Offline
Last seen: 2 hours 25 min ago
VESC Original
Joined: 2019-01-01 17:11
Posts: 126

In 6.05 Firmware its working to log PPM,ADC1,ADC2,ADC3. In vesc tool-> App Settings->General-> CAN Massages Rate 1 -> Show Help button. You have to activate CAN Status 6

palm369
Offline
Last seen: 1 month 1 week ago
VESC Free
Joined: 2018-08-28 16:46
Posts: 4

Thanks for your answer. I just tried that and this is the header from the CSV file generated. There is no PPM. In the help is written that it only then sends this messages on CAN.

ms_today input_voltage temp_mos_max temp_mos_1 temp_mos_2 temp_mos_3 temp_motor current_motor current_in d_axis_current q_axis_current erpm duty_cycle amp_hours_used amp_hours_charged watt_hours_used watt_hours_charged tachometer tachometer_abs encoder_position fault_code vesc_id d_axis_voltage q_axis_voltage ms_today_setup amp_hours_setup amp_hours_charged_setup watt_hours_setup watt_hours_charged_setup battery_level battery_wh_tot current_in_setup current_motor_setup speed_meters_per_sec tacho_meters tacho_abs_meters num_vescs ms_today_imu roll pitch yaw accX accY accZ gyroX gyroY gyroZ gnss_posTime gnss_lat gnss_lon gnss_alt gnss_gVel gnss_vVel gnss_hAcc gnss_vAcc

rascalangel
Offline
Last seen: 2 months 1 week ago
VESC Free
Joined: 2024-09-22 08:56
Posts: 1
palm369
Offline
Last seen: 1 month 1 week ago
VESC Free
Joined: 2018-08-28 16:46
Posts: 4

It seams that there is no possible solution for this. What is logged into the CSV from the mobile app is defined by the code of the APP and I cannot change this.

Anyway I found a solution that works for me:
I read a loadcell with a HX711 on an Arduino (ESP32 in my case) and then generate a analog output on a pin that I feed in the Motor_Temp Pin on the VESC. (ESP is also Powered from VESC and has Three wires in total connected: VCC, GND and Mot_Temp)
Like this I am able to measure 0-40 kg in 0.1 kg steps and log this as "Motor Temp" Value via the Mobile App on an iPhone. Its not 100% linear, but linear enough for my application.
Depending on what VESC you use you might slightly to adjust the Duty_min and _max values to fit. Otherwise you might have slight offset.

 

/*

This program reads an 100kg Load cell with the HX711 Chip on an ESP32 with OLED Display
It displays a graph with the weight on the display and notes the max value
It emulates an output which can be connected to the Motor Temp port on a VESC to log Weights 

*/


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <HX711.h>

// Analog output Emulation for 10k NTC Temp Sensor
#define PIN 13
#define Duty_min 371 // equals 40 kg Value (0-1024)
#define Duty_max 771 // Equals Zero Value (0-1024)
int Duty = 500;  // start value (0-1024)

// OLED display configuration
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// HX711 configuration
#define DOUT  15 // HX711 DOUT pin
#define CLK   14 // HX711 SCK pin
HX711 scale;

float calibration_factor = -45240; // This value needs to be adjusted based on your calibration
float weight = 0.0; // Float to store weight in grams
float maxWeight = 0.0; // Float to store max weight in grams
float weights[128]; // Array to hold the weight values for the graph in grams

const int graphHeight = 32; // Height of the graph in pixels
const int graphWidth = 128; // Width of the graph in pixels
const int graphBottom = 63; // Bottom of the graph

unsigned long lastUpdateTime = 0;
const int updateInterval = 31; // Update interval in milliseconds (approximately 32 Hz)

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

  // Output for Temp sensor
  ledcAttachChannel(PIN, 50000, 10, 0); // 50kHz, 10 Bit, Ch 0

  // Initialize I2C for OLED with SDA = GPIO5 and SCL = GPIO4
  Wire.begin(5, 4);
  
  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  
  // Clear display buffer
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  
  // Show initialization message
  display.setCursor(0, 25);
  display.setTextSize(2);
  display.println(F("Booting..."));
  display.display();

  // Initialize the scale
  scale.begin(DOUT, CLK);
  scale.set_scale(calibration_factor); // Set the calibration factor
  scale.tare(); // Reset the scale to 0
  
  // Initialize weights array
  for (int i = 0; i < graphWidth; i++) {
    weights[i] = 0.0; // Initialize weights array with floats (grams)
  }
}

void loop() {
  // Read weight from the load cell
  weight = scale.get_units() * 1000; // Get instantaneous weight reading in grams

  // Shift values in weights array to the left
  for (int i = 0; i < graphWidth - 1; i++) {
    weights[i] = weights[i + 1];
  }

  // Add current weight to end of weights array
  weights[graphWidth - 1] = weight;

  // Find maximum value in weights array
  maxWeight = 0.0; // Reset maxWeight to 0 before finding the maximum
  for (int i = 0; i < graphWidth; i++) {
    if (weights[i] > maxWeight) {
      maxWeight = weights[i];
    }
  }

  //Calc and output weight to Temp sensor
  Duty = map(weight, 0, 40000, Duty_max, Duty_min); // Convert Weight to Duty
  ledcWriteChannel(0, Duty); // write duty to channel zero

  // Display on OLED at appropriate interval
  unsigned long currentTime = millis();
  if (currentTime - lastUpdateTime >= updateInterval) {
    lastUpdateTime = currentTime;

    // Display clear and draw graph
    display.clearDisplay();

    // Draw graph border
    display.drawRect(0, graphBottom - graphHeight, SCREEN_WIDTH - 1, graphHeight +1, SSD1306_WHITE);

    // Draw graph in reversed direction (from right to left)
    for (int i = 0; i < graphWidth - 1; i++) {
      int y1 = map(weights[graphWidth - i - 1], 0, maxWeight, graphBottom, graphBottom - graphHeight);
      int y2 = map(weights[graphWidth - i - 2], 0, maxWeight, graphBottom, graphBottom - graphHeight);
      display.drawLine(SCREEN_WIDTH - i - 1, y1, SCREEN_WIDTH - i - 2, y2, SSD1306_WHITE);
    }

    // Display current weight in kilograms (upper half)
    display.setTextSize(2);
    display.setCursor(0, 0);
    display.print(weight / 1000, 1); // Display weight in kilograms with one decimal place
    display.println(F(" kg"));

    // Display max weight in current session (lower half)
    display.setTextSize(1);
    display.setCursor(0, 22);
    display.print(F("Max: "));
    display.print(maxWeight / 1000, 1); // Display max weight in kilograms with one decimal place
    display.println(F(" kg"));

    display.display();
  }
}