Stefan Postat August 22, 2016 Partajează Postat August 22, 2016 Are cineva un exemplu de program in MikroC pentru citirea ADC-ului HX711? Am folosit biblioteca asta http://libstock.mikroe.com/projects/view/1568/hx711-library dar citesc valori aiurea (seamana cu ce trebuie dar nu "rasare"). Unele functii din biblioteca nu sunt convins ca functioneaza corect dau nu am intepes cum se folosesc si PDF-ul cu "Ajutor" are greseli. Cu ATmega328 (exemple arduino) am citit HX711 din prima, deci e exclusa o greseala hardware.Nu ma intrebati de ce vreau sa folosc MikroC.Multumesc. Link spre comentariu
cristi7521 Postat August 22, 2016 Partajează Postat August 22, 2016 Poate te ajuta https://www.ccsinfo.com/forum/viewtopic.php?p=195622 Link spre comentariu
Stefan Postat August 22, 2016 Autor Partajează Postat August 22, 2016 Spre sfarsitul saptamanii portez codul in MikroC si vedem ce iese. Merci Link spre comentariu
mars01 Postat August 23, 2016 Partajează Postat August 23, 2016 (editat) Salut, Astept si eu placutele cu HX711 asa ca am portat un driver Arduino in mikroC pentru PIC16F (am preluat de aici: https://codebender.cc/library/HX711#HX711.cpp. Nu l-am incercat, posteaza si tu un feedback aici daca ai timp sa il incerci. Fisierul header HX711.h #ifndef HX711_H#define HX711_H#define HIGH 1#define LOW 0#define OUTPUT 0#define INPUT 1typedef unsigned char uint8t;typedef signed char int8t;typedef signed int int16t;typedef unsigned int uint16t;typedef unsigned long uint32t;typedef signed long int32t;extern sfr sbit SCK;extern sfr sbit SCK_dir;extern sfr sbit DOUT;extern sfr sbit DOUT_dir;// 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.uint8t 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 Bvoid set_gain(uint8t gain);// waits for the chip to be ready and returns a readinguint32t read();// returns an average reading; times = how many times to readuint32t read_average(uint8t times);// returns (read_average() - OFFSET), that is the current value without the tare weight; times = how many readings to dofloat get_value(uint8t times );// returns get_value() divided by SCALE, that is the raw value divided by a value obtained via calibration// times = how many readings to dofloat get_units(uint8t times);// set the OFFSET value for tare weight; times = how many times to read the tare valuevoid tare(uint8t times);// set the SCALE value; this value is used to convert the raw data to "human readable" data (measure units)void set_scale(float scale);// set OFFSET, the value that's subtracted from the actual reading (tare weight)void set_offset(int32t offset);// puts the chip into power down modevoid power_down();// wakes up the chip after power down modevoid power_up();#endif /* HX711_H */ Fisierul sursa HX711.c #include "HX711.h"uint8t GAIN;int32t OFFSET;float SCALE;uint8t is_ready() { return DOUT == LOW;}void set_gain(uint8t 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; } SCK = LOW; read();}uint32t read() { uint8t i,j; uint8t data_read[3]; // wait for the chip to become ready while (is_ready() == 0); // pulse the clock pin 24 times to read the data for (j = 3; j--;) { for (i = 8; i--;) { SCK = HIGH; if (DOUT) { data_read[j] |= (1 << i); } else { data_read[j] &= ~(1 << i); } SCK = LOW; } } // set the channel and the gain factor for the next reading using the clock pin for (i = 0; i < GAIN; i++) { SCK = HIGH; SCK = LOW; } data_read[2] ^= 0x80; return ((uint32t) data_read[2] << 16) | ((uint32t) data_read[1] << 8) | (uint32t) data_read[0];}uint32t read_average(uint8t times) { uint32t sum = 0; uint8t i; for (i = 0; i < times; i++) { sum += read(); } return sum / times;}float get_value(uint8t times) { return read_average(times) - OFFSET;}float get_units(uint8t times) { return get_value(times) / SCALE;}void tare(uint8t times) { float sum = read_average(times); set_offset(sum);}void set_scale(float scale) { SCALE = scale;}void set_offset(int32t offset) { OFFSET = offset;}void power_down() { SCK = LOW; SCK = HIGH;}void power_up() { SCK = LOW;} Atasat ai un proiect netestat cu un exemplu. HX711.zip Editat August 23, 2016 de mars01 Link spre comentariu
Stefan Postat August 24, 2016 Autor Partajează Postat August 24, 2016 @mars01 Nu am respectivul microcontroller asa ca am recompilat pentru 16F887 cu LCD-ul la portul D. La fiecare alimentare obtin cate o alta valoare si asa sta indiferent cat apas pe senzorii de greutate. Exemplu: 2513714176, 2066951522, 2228015744, 4133903104, 3053755136. Daca am valoarea 3053755136 si scot comunicatia de la HX711 obtin 3062160640. Fara HX711 conectat la PIC se comporta asemanator. Intre 16F887 si HX711 am 20cm de fir iar cele doua liniile SCK si DO nu sunt "trase" spre plus sau minus. Legat de codul din CCS nu am incercat nimic. De ce GAIN primeste valorile respective? Nu trebuia 25, 27, 26? void set_gain(uint8t 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; } SCK = LOW; read();} ... // set the channel and the gain factor for the next reading using the clock pin for (i = 0; i < GAIN; i++) { SCK = HIGH; SCK = LOW; } Link spre comentariu
mars01 Postat August 24, 2016 Partajează Postat August 24, 2016 (editat) Daca citim datasheet-ul (lucru care din lene nu l-am facut decat dupa ce am portat codul - daca o faceam inainte de portare probabil ca nici nu imi mai bateam capul sa caut pe net dupa un cod ci il faceam din start eu) o sa vedem ca lucrul cu acest cip este extrem de usor. Nu are registri, totul se face din timing-uri si numar de biti. Cu alte cuvinte. Primim cei 24 de biti care contin informatia, pe 24 pulsuri ale clock-ului (clock-ul este trimis de ucontroller). Daca dupa acesti 24 de biti (primiti pe 24 pulsuri clock) mai trimitem un puls clock atunci urmatoarea citire (cei 24 de biti) va fi cu un gain 128 (automat se selecteaza canalul A). Daca dupa cele 24 de pulsuri clock (pentru a "extrage cei 24 de biti de informatie - pe pinul SDO) trimitem inca doua pulsuri de clock atunci urmatoarea citire se va face cu un gain 32 (se selecteaza automat canalul B). Daca trimitem insa 3 pulsuri de clock suplimentare atunci urmatoarea citire se va face cu un gain 64 si se selecteaza automat canalul A. Secventa: SCK = HIGH;SCK = LOW; Genereaza un puls de clock pe iesirea controlerului, un pin botezat in program SCK (in realitate este un pin fizic, putem sa alegem orice pin controller care se poate seta ca iesire digitala). Daca pulsul de HIGH pe CLK dureaza mai mult de 60us atunci cipul intra in modul power down. Deci trebuie sa facem pulsurile de clock mai rapid de 60us ca sa nu punem cipul in power down. Ce mai trebuie stiut este ca informatia din cei 24 de biti este stocata in complement fata de 2 pentru a putea stoca valorile negative primite pe intrarea diferentiala. In datasheet este un exemplu de driver minimal in C: // atribuim anumiti pini unor variabile, cea de date, ADDO, si cea de clock, ADSKsbit ADDO = P1^5; // se asociaza un pin controler variabilei ADDO - al 5-lea din portul 1 ?sbit ADSK = P0^0; // se asociaza un pin controler variabilei ADSK - pinul 0 din portul 0 ?// functia de citire ADCunsigned long ReadCount(void){ unsigned long Count; // variabila care va contine informatia citita din ADC unsigned char i; // variabila contor pentru ciclul FOR ADDO=1; // se initializeaza variabila care contine informatia DATA cu 1 pentru a putea incepe procesul de shiftare cu un 1 logic pe bitul 0 ADSK=0; // clockul este LOW Count=0; // informatia citita din ADC este la acest moment, nula while(ADDO); // cat timp citim HIGH pe pinul asociat ADDO stai si asteapta LOW-ul care indica activitate ADC for (i=0;i<24;i++){ // executam de 24 de ori continutul buclei ADSK=1; // facem pinul clock HIGH si astfel incepem un puls de clock Count=Count<<1; // shiftam la stanga variabila Count care contine rezultatul ADSK=0; // facem pinul clock LOW si astfel finalizam un puls clock - deci vor fi 24 de pulsuri clock if(ADDO) Count++; // daca pe pinul de date asociat variabilei ADDO avem un HIGH atunci fa bitul 0 din rezultat HIGH - si va fi shiftat data viitoare la stanga } ADSK=1; // pinul clock HIGH - incepem un puls de clock Count=Count^0x800000; // facem toggle la bitul cel mai semnificativ ADSK=0; // pinul clock LOW - finalizam pulsul de clock si cum este un singur puls in final avem 24 + 1 = 25 pulsuri de clock deci un GAIN de 128. return(Count); // returnam valoarea citita de ADC.} Editat August 24, 2016 de mars01 Link spre comentariu
mars01 Postat August 24, 2016 Partajează Postat August 24, 2016 Mda, asa se intampla cand doar portezi codul altuia. Functia read() este gresita, mai exact ofera datele in complementul lui doi. Practic ce iese din functie trebuie inversat bit cu bit si adunat cu 1. Maine revin cu o biblioteca corectata. Link spre comentariu
mars01 Postat August 27, 2016 Partajează Postat August 27, 2016 (editat) Poti folosi urmatoarea functie corectata. Diferenta este ca in program va trebui sa testezi valoarea bitului 31 din rezultatul functiei pentru a afla: - daca este 1 atunci rezultatul este unul negativ, asigura-te ca faci bitul acesta LOW inainte de a folosi rezultatul - daca este 0 atunci rezultatul este unul pozitiv si il folosesti ca atare Ceva de genul (programul postat mai sus in arhiva trebuie modificat): enum semn {pozitiv;negativ;};res = read();if (res) { res ^= 0x80000000; semn = negativ; // codul tau ...... }else { semn = pozitiv; // codul tau} Si functia modificata: uint32t read() { uint8t i,j; uint8t data_read[3]; uint32t result; // wait for the chip to become ready while (is_ready() == 0); // pulse the clock pin 24 times to read the data for (j = 3; j--;) { for (i = 8; i--;) { SCK = HIGH; if (DOUT) { data_read[j] |= (1 << i); } else { data_read[j] &= ~(1 << i); } SCK = LOW; } } // set the channel and the gain factor for the next reading using the clock pin for (i = 0; i < GAIN; i++) { SCK = HIGH; SCK = LOW; } // if the reading is a negative one, bit23 is HIGH then, if (data_read[2] & 0x80) { // invert each bit in the result data_read[2] = ~data_read[2]; data_read[1] = ~data_read[1]; data_read[0] = ~data_read[0]; // put everything into a LONG variable and add 1 result = (((uint32t) data_read[2] << 16) | ((uint32t) data_read[1] << 8) | ((uint32t) data_read[0])) + 1; /* on bit 31 place a HIGH value so when you get in the main program this bit with HIGH value, you'll know you have a negative value Make sure that after you tested this bit, if HIGH you make this bit LOW so it will not be interpreted as a uint32 negative value */ result |= 0x80000000; return result; } else { return ((uint32t) data_read[2] << 16) | ((uint32t) data_read[1] << 8) | (uint32t) data_read[0]; }} Editat August 27, 2016 de mars01 Link spre comentariu
Vizitator NicolaPr Postat Ianuarie 9, 2017 Partajează Postat Ianuarie 9, 2017 (editat) Hello everybody. Thank very much Mars01 for ported code. I took it as a basis for mikroC, but during the week the library reworked under my requirements and i found a few mistakes. The most serious error is incorrectly read RAW data from the HX711. After a few days spent in the shuffle, the solution to this problem was very trivial. I added a delay of one microsecond between the pulses. I think Arduino working more slowly than PIC16 so in the original library is not necessary. The second mistake is the use of unsigned variables while the HX711 outputs 24 bits of signed data +/-. I also tried to reduce memory consumption by replacing 32-bit to 16-bit and remove floating point. So, here is my library and photos. Thank you all for your help! http://homus.com.ua/hx711/HX711_NicolaPr.zip http://homus.com.ua/hx711/schematic.jpg http://homus.com.ua/hx711/IMG_4207_.JPG Editat Ianuarie 9, 2017 de NicolaPr Link spre comentariu
mars01 Postat Ianuarie 9, 2017 Partajează Postat Ianuarie 9, 2017 (editat) Good job Nicola, At the moment when I've ported the code I had no HX711 IC (or board) available so I could not test it. In the meantime I did receive the boards ordered from eBay but ... I kind of drifted toward other projects and did not take the time to actually test the ported code. So thank you for doing this work and posting it here so others can benefit from it. Editat Ianuarie 9, 2017 de mars01 Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum