Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions examples/hx711_demo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
all : flash

TARGET:=hx711_demo
TARGET_MCU?=CH32V003

include ../../ch32fun/ch32fun.mk

flash : cv_flash
clean : cv_clean
17 changes: 17 additions & 0 deletions examples/hx711_demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# HX711 Load Cell Amplifier Example

This example shows how to interface a HX711 load cell amplifier.
The project provides a simple interface for calibration and reading weight values over the debug interface.

## Hardware Connections

- **HX711 Data Pin:** Connect to `PD4` (can be changed using define `HX711_DATA_PIN`).
- **HX711 Clock Pin:** Connect to `PD5` (can be changed using define `HX711_CLK_PIN`).

## Usage

1. Use `make` to upload firmware and `make monitor` to open the terminal
1. On startup, the device will tare (zero) the scale.
2. Enter commands:
- `C` + Enter: Starts calibration. Follow three prompts to place a known weight and enter its value.
- `V` + Enter: Reads and displays the current weight value.
10 changes: 10 additions & 0 deletions examples/hx711_demo/funconfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef _FUNCONFIG_H
#define _FUNCONFIG_H

// Place configuration items here, you can see a full list in ch32fun/ch32fun.h
// To reconfigure to a different processor, update TARGET_MCU in the Makefile

#define FUNCONF_USE_DEBUGPRINTF 1
#define FUNCONF_SYSTICK_USE_HCLK 1

#endif // _FUNCONFIG_H
178 changes: 178 additions & 0 deletions examples/hx711_demo/hx711.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/**
* HX711 Library for ch32fun
* Derived from the Arduino HX711 library by Bogdan Necula
* (https://github.com/bogde/HX711)
*
* MIT License
* (c) 2025 Alexander Mandera
* (c) 2018 Bogdan Necula
*/

#include "ch32fun.h"
#include <stdbool.h>

// control pins
#ifndef HX711_DATA_PIN
#define HX711_DATA_PIN PD4
#endif

#ifndef HX711_CLK_PIN
#define HX711_CLK_PIN PD5
#endif

#ifdef HX711_GAIN
#if HX711_GAIN == 128
#define HX711_GAIN 1
#elif HX711_GAIN == 64
#define HX711_GAIN 3
#elif HX711_GAIN == 32
#define HX711_GAIN 2
#endif
#else
#define HX711_GAIN_VALUE 1
#endif

static uint32_t hx711_scale = 0; // Scale factor * 100
static uint32_t hx711_offset = 0;

uint8_t hx711_shift_in() __attribute__((section(".srodata"))) __attribute__((used));
uint8_t hx711_shift_in() {
uint8_t value = 0;
uint8_t i;

for (i = 0; i < 8; ++i) {
funDigitalWrite(HX711_CLK_PIN, FUN_HIGH);
Delay_Us(1);
value |= funDigitalRead(HX711_DATA_PIN) << (7 - i);
funDigitalWrite(HX711_CLK_PIN, FUN_LOW);
Delay_Us(1);
}
return (uint8_t)value;
}

void hx711_init() {
// Clock pin as output
funPinMode(HX711_CLK_PIN, GPIO_Speed_10MHz | GPIO_CNF_OUT_PP);

// Data pin as input with pullup
funPinMode(HX711_DATA_PIN, GPIO_CFGLR_IN_PUPD);
funDigitalWrite(HX711_DATA_PIN, FUN_HIGH);
}

static inline void hx711_set_scale(uint32_t scale) {
hx711_scale = scale;
}

static inline uint32_t hx711_get_scale(void) {
return hx711_scale;
}

static inline void hx711_set_offset(uint32_t offset) {
hx711_offset = offset;
}

static inline uint32_t hx711_get_offset(void) {
return hx711_offset;
}

bool hx711_is_ready(void) {
return funDigitalRead(HX711_DATA_PIN) == FUN_LOW;
}

void hx711_wait_ready(uint32_t delay) {
while(!hx711_is_ready()) {
Delay_Ms(delay);
}
}

bool hx711_wait_ready_retry(uint8_t retries, uint32_t delay) {
uint8_t count = 0;
while(count < retries) {
if(hx711_is_ready()) {
return true;
}
Delay_Ms(delay);
count++;
}
return false;
}

bool hx711_wait_ready_timeout(uint32_t timeout, uint32_t delay) {
uint64_t start = SysTick->CNT;
uint64_t timeout_ticks = timeout * DELAY_MS_TIME;
while((SysTick->CNT - start) < timeout_ticks) {
if(hx711_is_ready()) {
return true;
}
Delay_Ms(delay);
}
return false;
}

uint32_t hx711_read(void) {
hx711_wait_ready(1); // Use 1ms delay

uint32_t value = 0;
uint8_t data[3] = {0};

// Disable interrupts during reading
__disable_irq();

// Read 24 bits
for (uint8_t i = 0; i < 3; i++) {
data[2 - i] = hx711_shift_in();
}

// Set gain for next reading
for (uint8_t i = 0; i < HX711_GAIN_VALUE; i++) {
funDigitalWrite(HX711_CLK_PIN, 1);
Delay_Us(1);
funDigitalWrite(HX711_CLK_PIN, 0);
Delay_Us(1);
}

__enable_irq();

// Combine bytes to 24-bit value
uint8_t filler = 0x00;
if(data[2] & 0x80) {
filler = 0xFF;
}

value = ( (uint32_t)filler << 24
| (uint32_t)data[2] << 16)
| ((uint32_t)data[1] << 8)
| data[0];

return value;
}

uint32_t hx711_read_average(uint8_t times) {
uint64_t sum = 0;
for (uint8_t i = 0; i < times; i++) {
sum += hx711_read();
}
return (uint32_t)(sum / times);
}

static inline uint32_t hx711_get_value(uint8_t times) {
return hx711_read_average(times) - hx711_offset;
}

static inline uint32_t hx711_get_units(uint8_t times) {
return hx711_get_value(times) * 100 / hx711_scale;
}

static inline void hx711_tare(uint8_t times) {
uint32_t sum = hx711_read_average(times);
hx711_set_offset(sum);
}

void hx711_power_down(void) {
funDigitalWrite(HX711_CLK_PIN, FUN_LOW);
funDigitalWrite(HX711_CLK_PIN, FUN_HIGH);
}

void hx711_power_up(void) {
funDigitalWrite(HX711_CLK_PIN, FUN_LOW);
}
118 changes: 118 additions & 0 deletions examples/hx711_demo/hx711_demo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#include "ch32fun.h"
#include <stdio.h>

#include "hx711.h"

static char input_buffer[64];
static int input_len = 0;

void calibration( void );

// handle_debug_input: only buffer input
void handle_debug_input(int numbytes, uint8_t *data)
{
for (int i = 0; i < numbytes && input_len < sizeof(input_buffer) - 1; i++)
{
char c = (char)data[i];
input_buffer[input_len++] = c;
if (c == '\n' || c == '\r')
{
input_buffer[input_len] = '\0';
}
}
}

// Calibration routine
void calibration( void )
{
int target_weight_int = 100; // grams * 100
int iterations = 3;
int divider_accum = 0;

hx711_set_scale( 1.0f ); // Reset scale
hx711_tare( 1 );
printf( "Ok\n" );

for ( int i = 0; i < iterations; i++ )
{
printf( "Place known weight and enter its value (g, integer):\n" );
// Wait for input
input_len = 0;
while ( 1 )
{
poll_input();
if ( input_len > 0 && ( input_buffer[input_len - 1] == '\n' || input_buffer[input_len - 1] == '\r' ) )
{
input_buffer[input_len - 1] = '\0';
// Convert string to integer
target_weight_int = 0;
for ( int j = 0; input_buffer[j] && j < 6; j++ )
{
if ( input_buffer[j] >= '0' && input_buffer[j] <= '9' )
{
target_weight_int = target_weight_int * 10 + ( input_buffer[j] - '0' );
}
}
break;
}
}
uint32_t measured_weight = hx711_get_units( 10 );
uint32_t divider = measured_weight / target_weight_int;
divider_accum += divider;

printf( "%d grams - Ok\n", target_weight_int );
input_len = 0;
}

uint32_t divider_final = divider_accum / iterations;

printf( "Calibration divider: %ld.%02ld\n", divider_final / 100, divider_final % 100 );
hx711_set_scale( divider_final );
printf( "Calibrated\n" );
}

// main loop: handle echo and command parsing
int main(void)
{
SystemInit();
while (!DebugPrintfBufferFree());

funGpioInitD();

printf("Start\n");
hx711_init();
hx711_tare(1);
printf("Tara done, give commands\n");

while (1)
{
poll_input();

// If a command is ready
if (input_len > 0 && (input_buffer[input_len - 1] == '\n' || input_buffer[input_len - 1] == '\r'))
{
// Echo back
for (int i = 0; i < input_len; i++)
putchar(input_buffer[i]);
input_buffer[input_len] = '\0';

printf("Received command: %s\n", input_buffer);

// Parse command
int b = strncmp(input_buffer, "C", 1);
printf("Compare result: %d\n", b);
if (strncmp(input_buffer, "C", 1) == 0)
{
printf("Calibration\n");
calibration();
}
else if (strncmp(input_buffer, "V", 1) == 0)
{
printf("Value\n");
uint32_t value = hx711_get_units(10);
printf("%ld\n", value);
}
input_len = 0;
}
}
}
4 changes: 4 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ build_src_filter = ${fun_base.build_src_filter} +<examples/branchless_gpio_lib>
extends = fun_base_003
build_src_filter = ${fun_base.build_src_filter} +<examples/hsitrim>

[env:hx711_demo]
extends = fun_base_003
build_src_filter = ${fun_base.build_src_filter} +<examples/hx711_demo>

[env:i2c_oled]
extends = fun_base_003
build_src_filter = ${fun_base.build_src_filter} +<examples/i2c_oled>
Expand Down