diff --git a/klippy/extras/hx71x.py b/klippy/extras/hx71x.py new file mode 100644 index 000000000000..19ff7ffae481 --- /dev/null +++ b/klippy/extras/hx71x.py @@ -0,0 +1,88 @@ +# HX710/HX711 weighing sensor support +# +# Copyright (C) 2023 guoge +# +# 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) diff --git a/src/Makefile b/src/Makefile index 8d771f9eb484..9841f2f0aaf0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ # Main code build rules -src-y += sched.c command.c basecmd.c debugcmds.c +src-y += sched.c command.c basecmd.c debugcmds.c hx71x.c src-$(CONFIG_HAVE_GPIO) += initial_pins.c gpiocmds.c stepper.c endstop.c \ trsync.c src-$(CONFIG_HAVE_GPIO_ADC) += adccmds.c diff --git a/src/hx71x.c b/src/hx71x.c new file mode 100644 index 000000000000..3b9ef5fcbd48 --- /dev/null +++ b/src/hx71x.c @@ -0,0 +1,141 @@ +// Commands for read weight from HX710A/HX711/HX712. +// +// Copyright (C) 2023 guoge +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include // 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 "generic/armcm_timer.h" // udelay + + +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"); + + +//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); + udelay(1); + + //wait dout to low. + //gpio_in_reset(dev->dt_in, 1); + int nCnt = 0; + while ( gpio_in_read(dev->dt_in) ) + { + 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); + udelay(1); + + count = count << 1; + + gpio_out_write(dev->sck_out, 0); + 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); + udelay(1); + gpio_out_write(dev->sck_out, 0); + 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; +}