Дозатор с двумя весами

avgustdon
Offline
Зарегистрирован: 28.02.2016

Необходимо сделать дозатор с двумя весами. Вижу два пути:

1.       Как-то подружить два контроллера весов HX711 с одним ардуино.

2.       Делать на двух ардуинах и чтобы они обменивались данными.

Оба варианта устраивают, но осилить не получается. Если кто-то знает третий простой вариант или реальная помощь как воплотить один из моих вариантов, буду премного благодарен.

b707
Offline
Зарегистрирован: 26.05.2017

контроллер HX711 требует для работы всего два пина. Думаю, на одну ардуину легко можно повесить 3-4 контроллера

avgustdon
Offline
Зарегистрирован: 28.02.2016

Это первое что я попробовал. Скетч прилагаю. Первые весы взвешивают правильно, а вторые не работают. Подозреваю что дело во взаимодействии скетча с библиотекой. Прошу помочь сдвинуть дело с мертвой точки. 

[code]
#include <HX711.h>        // Подключаем библиотеку HX711 для работы с АЦП hx711
HX711 scale(A1, A0);      // Указываем в какие пины подключен АЦП hx711 (DT(DOUT)  - pin A1, SCK - pin A0)
HX711 scale2(A2, A3);      // Указываем в какие пины подключен АЦП hx711 (DT(DOUT)  - pin A3, SCK - pin A2)

float myScale;            // Инициализируем переменную первых весов в которой будем хранить текущий вес
float myScale2;           // Инициализируем переменную вторых весов в которой будем хранить текущий вес

void setup() 
  {
  Serial.begin(9600);                         
  scale.set_scale(505);                       // Устанавливаем калибровочный коэффициент 1 весов.
  scale2.set_scale(505);                      // Устанавливаем калибровочный коэффициент 2 весов.
  scale.tare();                               // Сбрасываем весы 1 на 0
  scale2.tare();                              // Сбрасываем весы 2 на 0
  myScale = (scale.get_units());              // Запоминаем среднее значение на весах 1 без груза, но с учетом тары. 
  myScale2 = (scale2.get_units());            // Запоминаем среднее значение на весах 2 без груза, но с учетом тары. 
  }

void loop() 
{
    if ((scale.get_units()) )                         // взвешиваем на 1 весах
    {myScale = scale.get_units();} 

    if ((scale2.get_units()) )                         // взвешиваем на 2 весах
    {myScale2 = scale2.get_units();}       

      Serial.print("   ves1  "); 
      Serial.print(myScale); 
      Serial.print("      ves2  "); 
      Serial.println(myScale2); }           // выводим ПОКАЗАНИЯ ВЕСОВ 
[/code]

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
// Программа подключение 2х весов
#include <HX711.h>        // Подключаем библиотеку HX711 для работы с АЦП hx711
// ---------------------компоновка--------------------------------------------
HX711 scale1, scale2; // Создаем  1 и 2 весы
float myScale1, myScale2; // Переменные веса
//----------------------main()------------------------------------------------
void setup() {
  Serial.begin(9600);
  scale1.begin(/*DT(DOUT)*/A1,/*SCK*/A0);
  scale2.begin(/*DT(DOUT)*/A2,/*SCK*/A0);
  scale1.set_scale(505);                      // Устанавливаем калибровочный коэффициент 1 весов.
  scale2.set_scale(505);                      // Устанавливаем калибровочный коэффициент 2 весов.
  scale1.tare();                               // Сбрасываем весы 1 на 0
  scale2.tare();                              // Сбрасываем весы 2 на 0

}

void loop() {
  delay(200);
  myScale1 = scale1.get_units();              // Запоминаем среднее значение на весах 1 без груза, но с учетом тары.
  myScale2 = scale2.get_units();            // Запоминаем среднее значение на весах 2 без груза, но с учетом тары.
  Serial.println();
  Serial.print("ves1=");
  Serial.print(myScale1);
  Serial.print("   ves2 =");
  Serial.print(myScale2);
}

 

avgustdon
Offline
Зарегистрирован: 28.02.2016

Ругается в строке 4 вот так:

no matching function for call to 'HX711::HX711()'

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Тогда выкинте ту библиотеку и скачайте от сюда. https://github.com/bogde/HX711

Файл HX711.h https://github.com/bogde/HX711/blob/master/HX711.h

#ifndef HX711_h
#define HX711_h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class HX711
{
	private:
		byte PD_SCK;	// Power Down and Serial Clock Input Pin
		byte DOUT;		// Serial Data Output Pin
		byte GAIN;		// amplification factor
		long OFFSET = 0;	// used for tare weight
		float SCALE = 1;	// used to return weight in grams, kg, ounces, whatever

	public:
		// define clock and data pin, channel, and gain factor
		// channel selection is made by passing the appropriate gain: 128 or 64 for channel A, 32 for channel B
		// gain: 128 or 64 for channel A; channel B works with 32 gain factor only
		HX711(byte dout, byte pd_sck, byte gain = 128);

		HX711(); //<----- вот вам констуктор без значений. 

		virtual ~HX711();

		// Allows to set the pins and gain later than in the constructor
		void begin(byte dout, byte pd_sck, byte gain = 128);

		// 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 is_ready();

		// 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 set_gain(byte gain = 128);

		// waits for the chip to be ready and returns a reading
		long read();

		// returns an average reading; times = how many times to read
		long read_average(byte times = 10);

		// returns (read_average() - OFFSET), that is the current value without the tare weight; times = how many readings to do
		double get_value(byte times = 1);

		// 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 get_units(byte times = 1);

		// set the OFFSET value for tare weight; times = how many times to read the tare value
		void tare(byte times = 10);

		// set the SCALE value; this value is used to convert the raw data to "human readable" data (measure units)
		void set_scale(float scale = 1.f);

		// get the current SCALE
		float get_scale();

		// set OFFSET, the value that's subtracted from the actual reading (tare weight)
		void set_offset(long offset = 0);

		// get the current OFFSET
		long get_offset();

		// puts the chip into power down mode
		void power_down();

		// wakes up the chip after power down mode
		void power_up();
};

#endif /* HX711_h */

 

avgustdon
Offline
Зарегистрирован: 28.02.2016

С этой библиотекой все заработало.

Спасибо, qwone, вы опять меня выручили. )

Pablos
Pablos аватар
Offline
Зарегистрирован: 18.07.2017

Вожусь вот тоже с hx711, правда с одним пока.   Сейчас вот пробую разные фильтры вместо расчета среднего.

Кину пару умных мыслей...  )))

1. В примере от qwone оба АЦП висят на общем SCK выводе A0. Такое подключение можно использовать не только для экономии пинов, но и для экономии времени считывания. hx711 по-умолчанию (без перепайки) меряет не чаще 10 раз в секунду. Если переписать класс (главное - метод read), то можно читать два сразу, а не по очереди.

2. Не использую расчет среднего из этой библиотеки, а написал свой способ. В массив сохраняется N последних значений и сразу считается среднее. Тогда 1 измерение со средним происходит за 1 чтение АЦП. Иначе для N=10 нужно аж секунду ждать.

П.

 

 

 

 

 

avgustdon
Offline
Зарегистрирован: 28.02.2016

Pablos пишет:

Вожусь вот тоже с hx711, правда с одним пока.   Сейчас вот пробую разные фильтры вместо расчета среднего.

Кину пару умных мыслей...  )))

1. В примере от qwone оба АЦП висят на общем SCK выводе A0. Такое подключение можно использовать не только для экономии пинов, но и для экономии времени считывания. hx711 по-умолчанию (без перепайки) меряет не чаще 10 раз в секунду. Если переписать класс (главное - метод read), то можно читать два сразу, а не по очереди.

2. Не использую расчет среднего из этой библиотеки, а написал свой способ. В массив сохраняется N последних значений и сразу считается среднее. Тогда 1 измерение со средним происходит за 1 чтение АЦП. Иначе для N=10 нужно аж секунду ждать.

П.

 

Интересное решение. Скетч можете выложить?

Pablos
Pablos аватар
Offline
Зарегистрирован: 18.07.2017

#include <Q2HX711.h>
Q2HX711 hx711(A2, A3);

const byte dim = 5;         // количество измерений N
const float coef = 24507.0; // пересчет в кг

float initWeight;           // начальное значение показаний (тара)
float meanWeight;           // среднее значение веса за N измерений
float sumWeight;            // сумма N измерений
float lastWeight;           // последнее измерение
float filteredWeight;       // результат фильтрации

float measures[dim];        // массив для хранения  N измерений
unsigned long stimer, etimer;  

/**************************SETUP********************************/
void setup() {
  Serial.begin(9600);
  sumWeight = 0.0;
  for (byte i=0; i<dim; i++) {
      while (!hx711.readyToSend()) {;}
      measures[i] = hx711.read()/coef;
      sumWeight = sumWeight + measures[i];
      
      }

  initWeight = sumWeight/dim;
  
  
  for (byte i=0; i<dim; i++) {
    measures[i] = measures[i] - initWeight;
    }
    filteredWeight = measures[0];
    stimer = millis();
}
/***************************LOOP**********************************/
void loop() {
    if (hx711.readyToSend()) { 
// stimer = millis();
    Serial.print ("MEAN: ");
    Serial.print (measureWeight()*1000.0);
    Serial.print (" g, EXACT: ");
    Serial.print (lastWeight*1000.0);
    Serial.print (" g, FILTER: ");
    Serial.print (filteredWeight*1000.0);
    Serial.println (" g");
/*    etimer = millis()-stimer;
    
    Serial.print (etimer);
    Serial.println (" ms");
  */  }
  }

/****************************MEASURE AND FILTER*******************/
float measureWeight()  {

  sumWeight = 0.0;
  
  for (byte i=0; i<dim-1; i++) {
      measures[i] = measures[i+1];                   // сдвиг значений влево
      sumWeight = sumWeight + measures[i];           // подсчет суммы N-1 замеров
      }
      
  measures[dim-1] = hx711.read()/coef - initWeight;  // новый замер
  sumWeight = sumWeight + measures[dim-1];           // подсчет суммы N замеров
  
  meanWeight = sumWeight/dim;         // Среднее за N замеров
  lastWeight = measures[dim-1];       // Последнее неусредненное
  
//    апериодическое звено первого порядка  
//    Y0:=(K*X0+(Tf/SAMPLE_T*Y1))/((Tf/SAMPLE_T)+1);
//    Y1:=Y0;

//const float filter_T = 150;   // ms 
//const float sample_T = 100;   // ms
//const float filter_K = 1.0;  

  filteredWeight = (lastWeight+1.5*filteredWeight)/2.5;  // Фильтр Tf/Sample_T = 1.5
  
  return meanWeight;
  }

Есть еще более длинный вариант с расчетом СКО за N наблюдений.
Я пользуюсь СКО для анализа, что вес изменился.

Pablos
Pablos аватар
Offline
Зарегистрирован: 18.07.2017

Из графика хорошо видно, что простой фильтр первого порядка (Tf/Ts=2.5) дает практически те же результаты, что и усреднение по 5 значениям, а гемора меньше ))))   Программка из одой строчки! 
(синий - среднее, красный - реальный замер с шумом, зеленое - фильтр первого порядка)

Pablos
Pablos аватар
Offline
Зарегистрирован: 18.07.2017

Вот так еще лучше видно. Tf/Ts=4.5, N=15

DJON zzz
Offline
Зарегистрирован: 14.04.2019

Уважаемый ,,avgustdon,, из сие прочитанного складывается ощущение что ВЫ хотите собрать не что вроде ,, фасовки ,,
Так ли это?

avgustdon
Offline
Зарегистрирован: 28.02.2016

В общем да. Правда собрал уже.

dima2ko
Offline
Зарегистрирован: 08.11.2019

avgustdon пишет:

В общем да. Правда собрал уже.

 

Здравствуйте. Можно скетч глянуть?

egresr
Offline
Зарегистрирован: 22.11.2020
Всем привет.
Хотелось бы продолжить тему нескольких hx711 на одном Arduino/ESP8266.
 
Опишу "проблему".
Хочу попробовать организовать учет расходных материалов. 
Имеется шкаф с 8 полками на каждой по 4 весов.
 
Задача состоит в том чтобы одним ESP8266 :
1) с определенной периодичностью опрашивать эти 32 весов для контроля того, что весы не пусты (на них постоянно стоит тара с содержимым).
2) при снятии тары с весов в MySQL базу данных заносится последний опрошенный вес.
3) при возвращении тары на весы в бд заносится актуальный вес.
4) с определенной переодичностью скрипт пробегается по бд и сравнивает актуальный вес с минимально допустимым весом.
5) в случае достижения минимально допустимого веса, отправляется емайл ответственному лицу.
6) ответственное лицо должно иметь возможность контроля веса содержимого тары.
ну и т.д и т.п 
Описал все просто что-бы был понятен общий смысл.
 
Думал использовать расширители портов.
Т.е восемь связанных по I2C  расширителей на каждом по 4 весов.
 
Купил ESP8266 прикрутил для теста три расширителя. проверил на лампочках. Все мигает. Ну думаю щас я прикручу PCF8574 и ФСЁ. Уперся в суровую реальность. HX711 не хочет передавать данные.
 
Подключал так:
DT на P0 и SCK на P1 от HX711 первых весов (0x20),
DT на P2 и SCK на P3 от HX711 вторых весов (0x21) ну и тд.
 
Без расширителя портов, при подключении HX711 к ESP8266 данные с HX711передаются. ESP8266 запитан от 12 вольтового блока питания.
 
Может у кого есть идея как засаду обойти :) !
 
rkit
Offline
Зарегистрирован: 23.11.2016

Электронные весы нельзя постоянно держать под нагрузкой. Они начинают врать.

fsdb
Offline
Зарегистрирован: 24.10.2015

ребята на руках ничего нет. я вижу аналоговые пины в скетче. какие пины нужно использовать для весов. хочу подключить 4 датчика по углам

fsdb
Offline
Зарегистрирован: 24.10.2015

в библиотеке на сколько я понял любые цифровые и аналоговые подключаются просто как цифровые. что бы пины экономить? нужно подключить 4 датчика на углах

b707
Offline
Зарегистрирован: 26.05.2017

fsdb пишет:

ребята на руках ничего нет. я вижу аналоговые пины в скетче

в каком скетче?