Hi everyone,
I am using an STM32F407VET6 development board. I have a 5V DC SMPS, which I’m using to power both the relay and the HX711 module. The SMPS ground and the MCU ground are connected (common ground).
To reduce EMI, I’ve connected a snubber circuit across the relay's NO (Normally Open) and COM (Common) terminals.
I’ve created two FreeRTOS threads — one for valve control via the relay, and the other for reading weight data from the HX711 and sending it over UART. Both threads work perfectly until I connect AC power to the solenoid valve.
When the relay receives a HIGH signal from the MCU and switches the AC valve, the second thread (the one reading from HX711 and sending data over UART) stops working. No data is printed on the serial terminal after that.
I’ve attached the serial terminal output and the code for reference.
void Reset_GPIO_Pins(void) {
HAL_GPIO_WritePin(GPIOD,
GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4
| GPIO_PIN_5| GPIO_PIN_8 | GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,
GPIO_PIN_RESET);
}
void Set_Valves(uint32_t *pins, uint8_t pin_count) {
for (uint8_t i = 0; i < pin_count; i++) {
HAL_GPIO_WritePin(GPIOD, pins[i], GPIO_PIN_SET);
}
}
void cycle(uint32_t *pins, uint8_t pin_count,uint32_t delay) {
Set_Valves(pins, pin_count);
osDelay(delay);
Reset_GPIO_Pins();
}
int ValveOperatingTask(void) {
uint32_t cycle_4[] = { GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_5,GPIO_PIN_10, GPIO_PIN_11 };
uint32_t cycle_5[] = { GPIO_PIN_13, GPIO_PIN_2, GPIO_PIN_9 };
uint32_t cycle_6[] = { GPIO_PIN_15, GPIO_PIN_14, GPIO_PIN_2, GPIO_PIN_5,GPIO_PIN_10 };
uint32_t cycle_7[] = { GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_5,GPIO_PIN_10, GPIO_PIN_11 };
uint32_t cycle_8[] = { GPIO_PIN_13, GPIO_PIN_2, GPIO_PIN_9 };
uint32_t cycle_9[] = { GPIO_PIN_13, GPIO_PIN_4, GPIO_PIN_8 };
uint32_t cycle_10[] = { GPIO_PIN_13, GPIO_PIN_3, GPIO_PIN_12 };
while (1) {
vTaskDelay(pdMS_TO_TICKS(30000));
cycle(cycle_4, sizeof(cycle_4) / sizeof(cycle_4[0]), 10000);
vTaskDelay(pdMS_TO_TICKS(60000));
cycle(cycle_5, sizeof(cycle_5) / sizeof(cycle_5[0]), 60000);
vTaskDelay(pdMS_TO_TICKS(20000));
cycle(cycle_6, sizeof(cycle_6) / sizeof(cycle_6[0]), 10000);
vTaskDelay(pdMS_TO_TICKS(20000));
cycle(cycle_7, sizeof(cycle_7) / sizeof(cycle_7[0]), 22000);
vTaskDelay(pdMS_TO_TICKS(20000));
cycle(cycle_8, sizeof(cycle_8) / sizeof(cycle_8[0]), 10000);
vTaskDelay(pdMS_TO_TICKS(10000));
cycle(cycle_9, sizeof(cycle_9) / sizeof(cycle_9[0]), 10000);
vTaskDelay(pdMS_TO_TICKS(10000));
cycle(cycle_10, sizeof(cycle_10) / sizeof(cycle_10[0]),38000);
vTaskDelay(pdMS_TO_TICKS(20000));
}
}
this is my relay controling pattern which switching the ac valve
void HX711_Init(void) {
HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET);
}
int32_t HX711_Read(void) {
int32_t data = 0;
uint8_t i;
while (HAL_GPIO_ReadPin(HX711_DT_PORT, HX711_DT_PIN) == GPIO_PIN_SET)
;
for (i = 0; i < 24; i++) {
HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_SET); // SCK
//HAL_Delay(10);
data = (data << 1) | HAL_GPIO_ReadPin(HX711_DT_PORT, HX711_DT_PIN);
HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET); // SCK
//HAL_Delay(100);
}
HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_SET); // 25th pulse
HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET);
if (data & 0x800000) {
data |= 0xFF000000;
}
return data;
}
float HX711_GetWeight(int32_t offset, float scale) {
int32_t raw_value = HX711_Read();
float weight = ((float) (raw_value - offset) / scale);
// Avoid displaying small negative values due to noise
if (fabs(raw_value - offset) < 500) {
return 0.0;
}
return weight;
}
void WeightMeasurementTask(void) {
int32_t offset = 0;
float scale = NAN;
float last_weight = 0.0;
float weight = 0;
float get_wieght = 0;
float density = 1.0;
float volume_ml;
bool valve_active = 0; // State flag for valve operation
bool cycle6_active = 0; // Track if cycle 6 is active
bool cycle2_done = 0; // Flag to track if Cycle 2 (drain water) is complete
bool cycle7_done = 0; // Flag to track if Cycle 7 (fill water) is complete
bool cycle8_done = 0; // Flag to track if Cycle 8 (flush chemical A to V) is complete
bool cycle9_done = 0; // Flag to track if Cycle 9 (flush chemical V to A) is complete
bool cycle10_done = 0; // Flag to track if Cycle 10 (flush chemical DO to DI) is complete
FLASH_FlushCaches();
// Read saved offset and scale from Flash
Flash_ReadData(FLASH_USER_START_ADDR, &offset, sizeof(offset));
Flash_ReadData(FLASH_USER_START_ADDR + sizeof(offset), &scale,
sizeof(scale));
if (offset == -1 || isnan(scale)) {
osDelay(50);
offset = HX711_Read();
Flash_WriteData(FLASH_USER_START_ADDR, &offset, sizeof(offset));
Flash_WriteData(FLASH_USER_START_ADDR + sizeof(offset), &scale,
sizeof(scale));
}
else {
//printf("Offset and scale loaded from Flash.\n");
// snprintf(buffer5, sizeof(buffer5),
// "Offset and scale loaded from Flash.\n\r:");
// HAL_UART_Transmit(&huart1, (uint8_t*) buffer5, strlen(buffer5),
// HAL_MAX_DELAY);
// //// printf("Offset: %ld, Scale: %.2f\n", offset, scale);
//
// snprintf(buffer6, sizeof(buffer6), "Offset: %ld\n\r:", offset);
// HAL_UART_Transmit(&huart1, (uint8_t*) buffer6, strlen(buffer6),
// HAL_MAX_DELAY);
// snprintf(buffer7, sizeof(buffer7), "Scale: %.2f\n\r:", scale);
// HAL_UART_Transmit(&huart1, (uint8_t*) buffer7, strlen(buffer7),
// HAL_MAX_DELAY);
}
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
weight = HX711_GetWeight(offset, scale);
get_wieght = weight;
// if (weight > 3000.0) {
// snprintf(buffer, sizeof(buffer),
// "Overload! Max weight is 2kg.\n\r");
// HAL_UART_Transmit(&huart1, (uint8_t*) buffer, strlen(buffer),
// HAL_MAX_DELAY)
snprintf(buffer, sizeof(buffer)," Weight: %.f g\n\r",get_wieght);
HAL_UART_Transmit(&huart1, (uint8_t*) buffer, strlen(buffer),HAL_MAX_DELAY);
}
}
this hx711 fun for measuring the weight
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 1024);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* definition and creation of myTask02 */
osThreadDef(myTask02, StartTask02, osPriorityNormal, 0, 512);
myTask02Handle = osThreadCreate(osThread(myTask02), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* Start scheduler */
//osKernelStart();
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* Start scheduler */
osKernelStart();
this the main
void StartTask02(void const argument) {
/ USER CODE BEGIN StartTask02 /
/ Infinite loop */
ValveOperatingTask();
for (;;) {
osDelay(1);
}
/* USER CODE END StartTask02 */
}
here i am calling my valve fun
void StartTask02(void const argument) {
/ USER CODE BEGIN StartTask02 /
/ Infinite loop */
WeightMeasurementTask();
for (;;) {
osDelay(1);
}
/* USER CODE END StartTask02 */
}
and here i am calling the hx711 fun for weight measruing