Nytt bibliotek här! Denna gång har jag skrivit av HX711 viktgivare från bogde (som har MIT licens! för er sörrhommel) till STM32. Biblioteket fungerar! Jag delar med mig av det till er. Men jag har en fråga. Kan man använda SPI på detta bibliotek? Alltså halv-SPI då man bara läser från HX711.
Titta på denna kod. Här har vi alltså en digital utgång som kallas PD_SCK. Den pulserar.
Kod: Markera allt
// Set the channel and the gain factor for the next reading using the clock pin.
for (unsigned int i = 0; i < hx->GAIN; i++) {
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_SET);
for (uint16_t i = 0; i < SMALL_DELAY; i++) {} // Small delay
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_RESET);
for (uint16_t i = 0; i < SMALL_DELAY; i++) { } // Small delay
}
Kod: Markera allt
static uint8_t shiftIn(HX711 *hx, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;
for (i = 0; i < 8; ++i) {
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_SET);
for (uint16_t i = 0; i < SMALL_DELAY; i++) {
} // Small delay
if (bitOrder == LSBFIRST)
value |= HAL_GPIO_ReadPin(hx->DOUT_Port, hx->DOUT_Pin) << i;
else
value |= HAL_GPIO_ReadPin(hx->DOUT_Port, hx->DOUT_Pin) << (7 - i);
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_RESET);
for (uint16_t i = 0; i < SMALL_DELAY; i++) {
} // Small delay
}
return value;
}
Arbetsexempel:
Kod: Markera allt
#include "main.h"
#include "HX711/HX711.h"
HX711 hx;
int main(void)
{
HX711_begin(&hx, HX711_PD_SCK_GPIO_Port, HX711_PD_SCK_Pin, HX711_DOUT_GPIO_Port, HX711_DOUT_Pin, 128);
HX711_set_scale(&hx, 2280.f); // Set scale
HX711_tare(&hx, 0); // Reset scale to 0
while (1)
{
float value = HX711_get_units(&hx, 10);
char text[20];
sprintf(text, "%f", value);
}
}
Kod: Markera allt
#include "HX711.h"
// Make shiftIn() be aware of clockspeed for
// faster CPUs like ESP32, Teensy 3.x and friends.
// See also:
// - https://github.com/bogde/HX711/issues/75
// - https://github.com/arduino/Arduino/issues/6561
// - https://community.hiveeyes.org/t/using-bogdans-canonical-hx711-library-on-the-esp32/539
static uint8_t shiftIn(HX711 *hx, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;
for (i = 0; i < 8; ++i) {
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_SET);
for (uint16_t i = 0; i < SMALL_DELAY; i++) {
} // Small delay
if (bitOrder == LSBFIRST)
value |= HAL_GPIO_ReadPin(hx->DOUT_Port, hx->DOUT_Pin) << i;
else
value |= HAL_GPIO_ReadPin(hx->DOUT_Port, hx->DOUT_Pin) << (7 - i);
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_RESET);
for (uint16_t i = 0; i < SMALL_DELAY; i++) {
} // Small delay
}
return value;
}
void HX711_begin(HX711 *hx, GPIO_TypeDef* PD_SCK_Port, uint16_t PD_SCK_Pin, GPIO_TypeDef* DOUT_Port, uint16_t DOUT_Pin, uint8_t gain) {
// Digital output
hx->PD_SCK_Port = PD_SCK_Port;
hx->PD_SCK_Pin = PD_SCK_Pin;
// Digital pull-up input
hx->DOUT_Port = DOUT_Port;
hx->DOUT_Pin = DOUT_Pin;
// Set gain
HX711_set_gain(hx, gain);
}
bool HX711_is_ready(HX711 *hx) {
return !HAL_GPIO_ReadPin(hx->DOUT_Port, hx->DOUT_Pin);
}
void HX711_set_gain(HX711 *hx, uint8_t gain) {
switch (gain) {
case 128: // channel A, gain factor 128
hx->GAIN = 1;
break;
case 64: // channel A, gain factor 64
hx->GAIN = 3;
break;
case 32: // channel B, gain factor 32
hx->GAIN = 2;
break;
}
}
long HX711_read(HX711 *hx) {
// Wait for the chip to become ready.
HX711_wait_ready(hx, 0);
// Define structures for reading data into.
unsigned long value = 0;
uint8_t data[3] = { 0 };
uint8_t filler = 0x00;
// Pulse the clock pin 24 times to read the data.
data[2] = shiftIn(hx, MSBFIRST);
data[1] = shiftIn(hx, MSBFIRST);
data[0] = shiftIn(hx, MSBFIRST);
// Set the channel and the gain factor for the next reading using the clock pin.
for (unsigned int i = 0; i < hx->GAIN; i++) {
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_SET);
for (uint16_t i = 0; i < SMALL_DELAY; i++) {} // Small delay
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_RESET);
for (uint16_t i = 0; i < SMALL_DELAY; i++) { } // Small delay
}
// Replicate the most significant bit to pad out a 32-bit signed integer
if (data[2] & 0x80) {
filler = 0xFF;
} else {
filler = 0x00;
}
// Construct a 32-bit signed integer
value = (unsigned long) (filler << 24)
| (unsigned long) (data[2] << 16)
| (unsigned long) (data[1] << 8)
| (unsigned long) (data[0]);
return (long) value;
}
void HX711_wait_ready(HX711 *hx, unsigned long delay_ms) {
// Wait for the chip to become ready.
// This is a blocking implementation and will
// halt the sketch until a load cell is connected.
while (!HX711_is_ready(hx)) {
// Probably will do no harm on AVR but will feed the Watchdog Timer (WDT) on ESP.
// https://github.com/bogde/HX711/issues/73
HAL_Delay(delay_ms);
}
}
bool HX711_wait_ready_retry(HX711 *hx, int retries, unsigned long delay_ms) {
// Wait for the chip to become ready by
// retrying for a specified amount of attempts.
// https://github.com/bogde/HX711/issues/76
int count = 0;
while (count < retries) {
if (HX711_is_ready(hx)) {
return true;
}
HAL_Delay(delay_ms);
count++;
}
return false;
}
bool HX711_wait_ready_timeout(HX711 *hx, unsigned long timeout, unsigned long delay_ms) {
// Wait for the chip to become ready until timeout.
// https://github.com/bogde/HX711/pull/96
unsigned long millisStarted = HAL_GetTick();
while (HAL_GetTick() - millisStarted < timeout) {
if (HX711_is_ready(hx)) {
return true;
}
HAL_Delay(delay_ms);
}
return false;
}
long HX711_read_average(HX711 *hx, uint8_t times) {
long sum = 0;
for (uint8_t i = 0; i < times; i++) {
sum += HX711_read(hx);
// Probably will do no harm on AVR but will feed the Watchdog Timer (WDT) on ESP.
// https://github.com/bogde/HX711/issues/73
HAL_Delay(0);
}
return sum / times;
}
float HX711_get_value(HX711 *hx, uint8_t times) {
return HX711_read_average(hx, times) - hx->OFFSET;
}
float HX711_get_units(HX711 *hx, uint8_t times) {
return HX711_get_value(hx, times) / hx->SCALE;
}
void HX711_tare(HX711 *hx, uint8_t times) {
float sum = HX711_read_average(hx, times);
HX711_set_offset(hx, sum);
}
void HX711_set_scale(HX711 *hx, float scale) {
hx->SCALE = scale;
}
float HX711_get_scale(HX711 *hx) {
return hx->SCALE;
}
void HX711_set_offset(HX711 *hx, long offset) {
hx->OFFSET = offset;
}
long HX711_get_offset(HX711 *hx) {
return hx->OFFSET;
}
void HX711_power_down(HX711 *hx) {
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_SET);
}
void HX711_power_up(HX711 *hx) {
HAL_GPIO_WritePin(hx->PD_SCK_Port, hx->PD_SCK_Pin, GPIO_PIN_RESET);
}
Kod: Markera allt
#ifndef SRC_HX711_HX711_H_
#define SRC_HX711_HX711_H_
#include "main.h"
#include "stdbool.h"
#define SMALL_DELAY 10
#define LSBFIRST 0
#define MSBFIRST 1
typedef struct {
// Power Down and Serial Clock Input Pin - This must be output!
GPIO_TypeDef *PD_SCK_Port;
uint16_t PD_SCK_Pin;
// Serial Data Output Pin - This must be pull-up!
GPIO_TypeDef *DOUT_Port;
uint16_t DOUT_Pin;
uint8_t GAIN; // amplification factor
long OFFSET; // used for tare weight
float SCALE; // used to return weight in grams, kg, ounces, whatever
} HX711;
// Initialize library with data output pin, clock input pin and gain factor.
// Channel selection is made by passing the appropriate gain:
// - With a gain factor of 64 or 128, channel A is selected
// - With a gain factor of 32, channel B is selected
// The library default is "128" (Channel A).
void HX711_begin(HX711 *hx, GPIO_TypeDef* PD_SCK_Port, uint16_t PD_SCK_Pin, GPIO_TypeDef* DOUT_Port, uint16_t DOUT_Pin, uint8_t gain);
// Check if HX711 is ready
// from the datasheet: When output data is not ready for retrieval, digital output pin DOUT is high. Serial clock
// input PD_SCK should be low. When DOUT goes to low, it indicates data is ready for retrieval.
bool HX711_is_ready(HX711 *hx);
// Wait for the HX711 to become ready
void HX711_wait_ready(HX711 *hx, unsigned long delay_ms);
bool HX711_wait_ready_retry(HX711 *hx, int retries, unsigned long delay_ms);
bool HX711_wait_ready_timeout(HX711 *hx, unsigned long timeout, unsigned long delay_ms);
// set the gain factor; takes effect only after a call to read()
// channel A can be set for a 128 or 64 gain; channel B has a fixed 32 gain
// depending on the parameter, the channel is also set to either A or B
void HX711_set_gain(HX711 *hx, uint8_t gain);
// waits for the chip to be ready and returns a reading
long HX711_read(HX711 *hx);
// returns an average reading; times = how many times to read
long HX711_read_average(HX711 *hx, uint8_t times);
// returns (read_average() - OFFSET), that is the current value without the tare weight; times = how many readings to do
float HX711_get_value(HX711 *hx, uint8_t times);
// returns get_value() divided by SCALE, that is the raw value divided by a value obtained via calibration
// times = how many readings to do
float HX711_get_units(HX711 *hx, uint8_t times);
// set the OFFSET value for tare weight; times = how many times to read the tare value
void HX711_tare(HX711 *hx, uint8_t times);
// set the SCALE value; this value is used to convert the raw data to "human readable" data (measure units)
void HX711_set_scale(HX711 *hx, float scale);
// get the current SCALE
float HX711_get_scale(HX711 *hx);
// set OFFSET, the value that's subtracted from the actual reading (tare weight)
void HX711_set_offset(HX711 *hx, long offset);
// get the current OFFSET
long HX711_get_offset(HX711 *hx);
// puts the chip into power down mode
void HX711_power_down(HX711 *hx);
// wakes up the chip after power down mode
void HX711_power_up(HX711 *hx);
#endif /* SRC_HX711_HX711_H_ */