Go Down

Topic: Celle di carico con HX711 (Read 2414 times) previous topic - next topic

steve-cr

Disturbo perché uso celle di carico da 10 o 20 Kg. con amlificatore convertitore Analogico Digitale HX711.
Su Arduino nessun problema di lettura e taratura grazie alla libreria.
Mi chiedevo se nessuno le ha mai usate su ARM o su altre MPU e/o come ha fatto a sviluppare un codice, dato che il data sheet è un po' limitato...

Grazie in anticipo
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

gpb01

#1
Mar 30, 2018, 05:59 pm Last Edit: Mar 30, 2018, 05:59 pm by gpb01
... Mi chiedevo se nessuno le ha mai usate su ARM o su altre MPU e/o come ha fatto a sviluppare un codice, dato che il data sheet è un po' limitato...
... mai fatto quindi NON posso aiutarti direttamemte, ma ... visto che hai la libreria per Arduino, non dovrebbe essere difficile capire come funziona ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

uwefed

Cosa non é chiaro in questa spiegazione?

Quote
Serial Interface
Pin PD_SCK and DOUT are used for data
retrieval, input selection, gain selection and power
down controls.
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. By
applying 25~27 positive clock pulses at the
PD_SCK pin, data is shifted out from the DOUT
output pin. Each PD_SCK pulse shifts out one bit,
starting with the MSB bit first, until all 24 bits are
shifted out. The 2h pulse at PD_SCK input will
pull DOUT pin back to high (Fig.2).
Input and gain selection is controlled by the
number of the input PD_SCK pulses (Table 3).
PD_SCK clock pulses should not be less than 25
or more than 27 within one conversion period, to
avoid causing serial communication error.
con i 24 Impulsi sul PD_SCK trasmetti il dato misurato. In aggiunta di questi con 1, 2o 3 impulsi selezioni l' amplificazione e l' entrata.
Ciao Uwe

steve-cr

E' il "dopo" i 24-27 impulsi che la cosa non viene spiegata, quindi non mi è chiara...
Il treno di impulsi che proviene da DATA cioè la lettura, come la interpreto?
E' una word? 8 bit? 16 bit?
Senza un oscilloscopio non lo vedo...
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

gpb01

#4
Mar 31, 2018, 07:09 pm Last Edit: Mar 31, 2018, 07:09 pm by gpb01
E' il "dopo" i 24-27 impulsi che la cosa non viene spiegata, quindi non mi è chiara...
Ripeto, ma se apri la libreria (... che ho capito tu hai per Arduino) e guardi come fanno ?

Guglielmo
Search is Your friend ... or I am Your enemy !

steve-cr

Code: [Select]
#include <Arduino.h>
#include <HX711.h>

#if ARDUINO_VERSION <= 106
    // "yield" is not implemented as noop in older Arduino Core releases, so let's define it.
    // See also: https://stackoverflow.com/questions/34497758/what-is-the-secret-of-the-arduino-yieldfunction/34498165#34498165
    void yield(void) {};
#endif

HX711::HX711(byte dout, byte pd_sck, byte gain) {
begin(dout, pd_sck, gain);
}

HX711::HX711() {
}

HX711::~HX711() {
}

void HX711::begin(byte dout, byte pd_sck, byte gain) {
PD_SCK = pd_sck;
DOUT = dout;

pinMode(PD_SCK, OUTPUT);
pinMode(DOUT, INPUT);

set_gain(gain);
}

bool HX711::is_ready() {
return digitalRead(DOUT) == LOW;
}

void HX711::set_gain(byte gain) {
switch (gain) {
case 128: // channel A, gain factor 128
GAIN = 1;
break;
case 64: // channel A, gain factor 64
GAIN = 3;
break;
case 32: // channel B, gain factor 32
GAIN = 2;
break;
}

digitalWrite(PD_SCK, LOW);
read();
}

long HX711::read() {
// wait for the chip to become ready
while (!is_ready()) {
// Will do nothing on Arduino but prevent resets of ESP8266 (Watchdog Issue)
yield();
}

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(DOUT, PD_SCK, MSBFIRST);
data[1] = shiftIn(DOUT, PD_SCK, MSBFIRST);
data[0] = shiftIn(DOUT, PD_SCK, MSBFIRST);

// set the channel and the gain factor for the next reading using the clock pin
for (unsigned int i = 0; i < GAIN; i++) {
digitalWrite(PD_SCK, HIGH);
digitalWrite(PD_SCK, LOW);
}

// 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 = ( static_cast<unsigned long>(filler) << 24
| static_cast<unsigned long>(data[2]) << 16
| static_cast<unsigned long>(data[1]) << 8
| static_cast<unsigned long>(data[0]) );

return static_cast<long>(value);
}

long HX711::read_average(byte times) {
long sum = 0;
for (byte i = 0; i < times; i++) {
sum += read();
yield();
}
return sum / times;
}

double HX711::get_value(byte times) {
return read_average(times) - OFFSET;
}

float HX711::get_units(byte times) {
return get_value(times) / SCALE;
}

void HX711::tare(byte times) {
double sum = read_average(times);
set_offset(sum);
}

void HX711::set_scale(float scale) {
SCALE = scale;
}

float HX711::get_scale() {
return SCALE;
}

void HX711::set_offset(long offset) {
OFFSET = offset;
}

long HX711::get_offset() {
return OFFSET;
}

void HX711::power_down() {
digitalWrite(PD_SCK, LOW);
digitalWrite(PD_SCK, HIGH);
}

void HX711::power_up() {
digitalWrite(PD_SCK, LOW);
}


Guglielmo, questa è la libreria, ma anche io ho i miei limiti.... :smiley-confuse:
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

uwefed

Code: [Select]

long HX711::read() {
// wait for the chip to become ready
while (!is_ready()) {
// Will do nothing on Arduino but prevent resets of ESP8266 (Watchdog Issue)
yield();
}

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(DOUT, PD_SCK, MSBFIRST);
data[1] = shiftIn(DOUT, PD_SCK, MSBFIRST);
data[0] = shiftIn(DOUT, PD_SCK, MSBFIRST);

// set the channel and the gain factor for the next reading using the clock pin
for (unsigned int i = 0; i < GAIN; i++) {
digitalWrite(PD_SCK, HIGH);
digitalWrite(PD_SCK, LOW);
}

// 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 = ( static_cast<unsigned long>(filler) << 24
| static_cast<unsigned long>(data[2]) << 16
| static_cast<unsigned long>(data[1]) << 8
| static_cast<unsigned long>(data[0]) );

return static_cast<long>(value);
}


Ciao Uwe

steve-cr

#7
Apr 02, 2018, 08:53 pm Last Edit: Apr 02, 2018, 08:56 pm by steve-cr
Grazie Uwe, ma sono partito più terra terra.
E questo funziona !!!!!
Quindi lo stesso codice scritto più o meno uguale sul TPAC1007 (vedi su google) dovrebbe funzionare modulando opportunamente con qualche delay...


Code: [Select]


 int data = 0;
 String StringOne = "";


void setup() {
  
 pinMode(3, OUTPUT);
 pinMode(4, INPUT);
 digitalWrite (3,LOW);
 Serial.begin(9600);
  
}

void loop() {

if (digitalRead (4) == LOW) {
for (int i=0; i <= 24; i++){
  
      digitalWrite (3,HIGH);
      data = digitalRead (4);
      //delay (1);
      digitalWrite (3,LOW);
      StringOne = String(StringOne + String(data));      
     }
    
 Serial.println (StringOne);
 StringOne = "";
 
 }
}

Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

steve-cr

Adesso dovrei convertire la stringa in numero binario e da numero binario a numero decimale.....

Ma ce la posso fare....
Forse ! :o
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

uwefed

Ti ripeto:
Code: [Select]

// 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 = ( static_cast<unsigned long>(filler) << 24
| static_cast<unsigned long>(data[2]) << 16
| static_cast<unsigned long>(data[1]) << 8
| static_cast<unsigned long>(data[0]) );


Ciao Uwe

steve-cr

Ti ringrazio Uwe ma ho visto che hai il dono della sintesi ...
La mia domanda è: il codice della libreria che ho postato, e che ho capito abbastanza, è un codice che può essere inserito in Atmel, ma se lo inserisco in un'altra MPU pensi che possa funzionare?
Perché, per esempio, le prime due righe #include mi sembra che abbiano poco senso dato che si riferiscono a Arduino, ma anche la successiva IF Arduino_Version...

Per la conversione l'ho capita poco, ma copio e incollo e va bene così.
Dal data sheet ho visto che i bit che escono partono dal MSB e arrivano al LSB quindi sono "in fila" anche se dal binario vedo che ad un certo punto della pressione sulla cella i primi 8 bit diventano di colpo tutti 1 mentre prima erano tutti 0 e la cosa è strana...





Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

gpb01

La mia domanda è: il codice della libreria che ho postato, e che ho capito abbastanza, è un codice che può essere inserito in Atmel, ma se lo inserisco in un'altra MPU pensi che possa funzionare? ...
Ma ovviamente NO e non è neanche Atmel, è Arduino IDE dato che, se elimini il framework "Wiring", che ti mette a disposizione l'IDE ... ti scordi tutte le digitalWrite(), digitalRead() ecc. ecc.

Per portarlo su un'altra MCU occorre CAPIRE esattamente cosa fa e riscriverlo totalmente nell'ambiente di sviluppo dell'altra MCU e ... per farlo, occorre conoscere bene il linguaggio di programmazione sia di Arduino che, ovviamente, dell'altra MCU.

Su che MCU pensavi di farlo girare ?

Guglielmo
Search is Your friend ... or I am Your enemy !

steve-cr

E' una ARM926JE, provvista di touch screen, un bel prodotto tutto italiano di una ditta torinese, la MECT, programmabile attraverso QTcreator.

Però, senza scomodare il C++, ho visto in Arduino, SENZA caricare la libreria, che dando i 24 impulsi ottengo i 24 bit e poi do il 25' impulso per dire che la prossima lettura la voglio sempre con gain a 128.

Quindi farò ancora così su quella CPU, dato che non esiste libreria.

Ora che ho letto meglio il data sheet la cosa è abbastanza semplice: quando i dati sono disponibili per la trasmissione sul pin DATA, questo passa a LOW e da quel momento inviando 24 impulsi sul pin PD_SCK ottengo come risposta sul pin DATA i 24 bit corrispondenti alla lettura. Poi termino inviando il 25esimo impulso per chiudere il pin DATA a HIGH fino a quando questo si riposizionerà su LOW per dirmi che è pronto alla prossima trasmissione.

Fondamentalmente non c'è bisogno di una libreria se non si vogliono cose particolari (quello che diciamo spesso qui dove, se possibile, si preferisce consigliare di non usare troppe librerie).
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

gpb01

#13
Apr 03, 2018, 11:43 am Last Edit: Apr 03, 2018, 11:43 am by gpb01
Fondamentalmente non c'è bisogno di una libreria se non si vogliono cose particolari (quello che diciamo spesso qui dove, se possibile, si preferisce consigliare di non usare troppe librerie).
Cosa verissima nel ... 75% dei casi ! ... C'è un 25% di casi in cui il lavoro sarebbe talmente tanto che ... sarebbe come "reinventare la ruota", ma effettivamnete spessissimo, per le proprie esigenze ... conviene scriversi quelle poche istruzioni che servono senza scomodare librerie che, ovviamnete, fanno di tutto e di più ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

steve-cr

Vabbé, non ci vuole un genio.....

Adesso che l'ho capito, però    :D  :D  :D

Il data sheet parla chiaro, è che mi sono fatto "spaventare" dalle temporizzazioni, dai microsecondi, mentre sono temporizzazioni minime. Ma se leggo "con calma" funziona ugualmente (comunque entro i 50 ms).

Praticamente il pin DATA è HIGH e passa a LOW quando il treno di 24bit è pronto per la trasmissione dalla schedina HX711 ad Arduino.

Allora invio 24 impulsi sul pin SCK e ad ogni impulso la schedina risponde con un bit sul pin DATA (HIGH=1 e LOW=0) che metto in una stringa.

Termino con un ulteriore impulso (oppure due oppure tre) per comunicare alla schedina con che amplificazione voglio la prossima lettura.

FINITO.

Code: [Select]
int data = 0;
String StringOne = "";

void setup() {

  pinMode(3, OUTPUT);
  pinMode(4, INPUT);

  digitalWrite (3,LOW);
  Serial.begin(9600);

}

void loop() {

  if (digitalRead (4) == LOW) { //quando è LOW mando 24 impulsi su D3 per leggere 24 bit su D4
    for (int i=0; i <= 23; i++){

      digitalWrite (3,HIGH);
      data = digitalRead (4);
      digitalWrite (3,LOW);

      StringOne = String(StringOne + String(data));     
    }

    digitalWrite (3,HIGH);
    delay (21);
    digitalWrite (3,LOW);

    Serial.println (StringOne);

    StringOne = "";

  }
}



La stringa di 1 e 0 è perfetta e pronta per la conversione in decimale senza l'uso di librerie....

Qualche idea per convertire una stringa di 24 caratteri in un numero decimale?
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

Go Up