Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add weighing sensor HX710/HX711/HX712 #6350

Closed
wants to merge 2 commits into from
Closed
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
88 changes: 88 additions & 0 deletions klippy/extras/hx71x.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# HX710/HX711 weighing sensor support
#
# Copyright (C) 2023 guoge <[email protected]>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging
import mcu

######################################################################
# Compatible Sensors:
# HX710A / HX711 / HX712
######################################################################


class HX71X:
def __init__(self, config):
self.printer = config.get_printer()
self.name = config.get_name().split()[-1]
self.reactor = self.printer.get_reactor()
self.mcu = mcu.get_printer_mcu(self.printer,
config.get('hx71x_mcu', 'mcu'))
self.oid = self.mcu.create_oid()

# Determine pin from config
ppins = config.get_printer().lookup_object("pins")
sck_params = ppins.lookup_pin(config.get('hx71x_sck_pin'))
dout_params = ppins.lookup_pin(config.get('hx71x_dout_pin'))

self.mcu.add_config_cmd(
"config_hx71x oid=%d sck_pin=%s dout_pin=%s"
% (self.oid, sck_params['pin'], dout_params['pin']))

#update period
self.report_time = config.getfloat('hx71x_report_time', 2,
minval=0.02)

#unit scale
self.scale = config.getfloat('hx71x_scale', 0.001)

self.weight = 0.0
self.sample_timer = self.reactor.register_timer(self._sample_hx71x)
self.printer.add_object("hx71x " + self.name, self)
self.printer.register_event_handler("klippy:connect",
self.handle_connect)

self.cmd_queue = self.mcu.alloc_command_queue()
self.mcu.register_config_callback(self.build_config)

def handle_connect(self):
self.reactor.update_timer(self.sample_timer, self.reactor.NOW)
return

def build_config(self):
self.read_hx71x_cmd = self.mcu.lookup_query_command(
"read_hx71x oid=%c read_len=%u",
"read_hx71x_response oid=%c response=%*s", oid=self.oid,
cq=self.cmd_queue)

def read_hx71x(self, read_len):
return self.read_hx71x_cmd.send([self.oid, read_len])

def setup_callback(self, cb):
self._callback = cb

def get_report_time_delta(self):
return self.report_time

def _sample_hx71x(self, eventtime):
params = self.read_hx71x(4)

response = bytearray(params['response'])
w = int.from_bytes(response, byteorder='little', signed=True)
self.weight = w * self.scale # weight scale

logging.info(" read hx711 @ %.3f , weight:%.2f", eventtime, self.weight)
return eventtime + self.report_time

def get_status(self, eventtime):
return {
'weight': round(self.weight, 2)
}


def load_config(config):
return HX71X(config)

def load_config_prefix(config):
return HX71X(config)
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

src-y += sched.c command.c basecmd.c debugcmds.c
src-$(CONFIG_HAVE_GPIO) += initial_pins.c gpiocmds.c stepper.c endstop.c \
trsync.c
trsync.c hx71x.c
src-$(CONFIG_HAVE_GPIO_ADC) += adccmds.c
src-$(CONFIG_HAVE_GPIO_SPI) += spicmds.c
src-$(CONFIG_HAVE_GPIO_SDIO) += sdiocmds.c
Expand Down
151 changes: 151 additions & 0 deletions src/hx71x.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Commands for read weight from HX710A/HX711/HX712.
//
// Copyright (C) 2023 guoge <[email protected]>
//
// This file may be distributed under the terms of the GNU GPLv3 license.

#include <string.h> // memcpy
#include "autoconf.h" //
#include "basecmd.h" //oid_alloc
#include "command.h" //sendf
#include "sched.h" //DECL_COMMAND
#include "board/gpio.h" //GPIO/read/setup
#include "board/misc.h" // timer_read_time



struct hx71x_s {
struct gpio_out sck_out;
struct gpio_in dt_in;
long weight_tare;
long pulse_count;
};

long HX711_Read(struct hx71x_s *dev);
void HX711_Get_WeightTare(struct hx71x_s *dev);
long HX711_Get_Weight(struct hx71x_s *dev);


void command_config_hx71x(uint32_t *args)
{
struct hx71x_s *hx71x = oid_alloc(args[0], command_config_hx71x
, sizeof(*hx71x));
hx71x->sck_out = gpio_out_setup(args[1], 1);
hx71x->dt_in = gpio_in_setup(args[2], 1);
gpio_out_write(hx71x->sck_out, 0);

hx71x->weight_tare = 0;
}
DECL_COMMAND(command_config_hx71x,
"config_hx71x oid=%c sck_pin=%u dout_pin=%u");


struct hx71x_s * hx71x_oid_lookup(uint8_t oid)
{
return oid_lookup(oid, command_config_hx71x);
}


void command_read_hx71x(uint32_t * args)
{
static int s_nCnt = 0;
s_nCnt++;

uint8_t oid = args[0];
struct hx71x_s *dev = hx71x_oid_lookup(args[0]);
dev->pulse_count = args[1];
uint8_t data_len = 4;
uint8_t data[data_len];

long weight = HX711_Get_Weight(dev);
data[0] = weight & 0xFF;
data[1] = (weight>>8) & 0xFF;
data[2] = (weight>>16) & 0xFF;
data[3] = (weight>>24) & 0xFF;
sendf("read_hx71x_response oid=%c response=%*s", oid, data_len, data);
}
DECL_COMMAND(command_read_hx71x, "read_hx71x oid=%c read_len=%u");


// microsecond delay helper
static inline void
hx71x_udelay(uint32_t usecs)
{
uint32_t end = timer_read_time() + timer_from_us(usecs);
while (!timer_is_before(end, timer_read_time()));
}


//read data form HX711
long HX711_Read(struct hx71x_s *dev)
{
//gpio_out_reset(dev->sck_out, 0);
gpio_out_write(dev->sck_out, 0);
hx71x_udelay(1);

//wait dout to low.
//gpio_in_reset(dev->dt_in, 1);
int nCnt = 0;
while ( gpio_in_read(dev->dt_in) )
{
hx71x_udelay(1);
if (nCnt++> 100 * 1000)
return 0;
}

//read 24bit data.
unsigned long count=0;
for (int i = 0; i < 24; i++)
{
gpio_out_write(dev->sck_out, 1);
hx71x_udelay(1);

count = count << 1;

gpio_out_write(dev->sck_out, 0);
hx71x_udelay(1);

if( gpio_in_read(dev->dt_in) )
count++;
}

//last clk, total 25/26/27
int n = 1;
if( dev->pulse_count==26 )
n = 2;
else if( dev->pulse_count==27 )
n = 3;

for (int i = 0; i < n; i++)
{
gpio_out_write(dev->sck_out, 1);
hx71x_udelay(1);
gpio_out_write(dev->sck_out, 0);
hx71x_udelay(1);
}

count ^= 0x800000;
return count;
}

//set weight tare.
void HX711_Get_WeightTare(struct hx71x_s* dev)
{
dev->weight_tare = HX711_Read(dev);
}

//get weight
long HX711_Get_Weight(struct hx71x_s* dev)
{
static int s_nCnt = 0;

long value = HX711_Read(dev);

if( s_nCnt<2 ) //reset weight tare at 1/2 times.
{
s_nCnt++;
dev->weight_tare = value;
}

return value - dev->weight_tare;
}
Loading