Una cèl·lula de càrrega és un sensor que permet mesurar forces i, per tant, saber el pes dels objectes. Una cèl·lula de càrrega típica consisteix en una peça que es subjecta per un costat i se li aplica una força al costat contrari. Aquesta força provoca una flexió a la peça que depèn de la força aplicada.

Per mesurar la flexió de la peça, fem servir galques extensiomètriques. Una galga extensiomètrica té una resistència elèctrica que varia en ser estirada o comprimida. Les galgues que posem a la part superior de la barra s'estiraran i les de la part inferior es comprimiran. Si connectem quatre galgues formant un pont i alimentem a tensió constant per dos extrems oposats obtindrem una tensió de sortida als altres dos extrems que dependrà de la força aplicada. La tensió de sortida és molt petita i, per tant, caldrà algun sistema amplificador per poder-la llegir amb el microcontrolador.
Nosaltres farem servir una cèl·lula de càrrega de 10 kg que connectarem a un amplificador que es basa en el circuit integrat HX711. Aquest amplificador no dona un senyal analògic sinó que proporciona la lectura a partir d'una comunicació sèrie. El circuit serà el següent.

El circuit integrat HX711 ens donarà un valor de 24 bits que correspondrà a la lectura del sensor. El nostre programa guardarà el valor llegit a la variable Lectura:3 de manera que Lectura+2 tindrà el byte més significatiu i Lectura el byte meys significatiu.
Per llegir el valor, farem un bucle de 24 iteracions. A cada iteració activarem RC6 per demanar un nou bit i llegirem el valor a RC4. Tot seguit desactivarem RC6. El circuit integrat HX711 té tres modes de treball diferents que se seleccionen en funció del nombre de polsos que es fan en el procés de lectura. En el nostre cas ens interessa llegir el port A amb guany elevat, que correspon a 25 polsos. Per això, un cop llegits els 24 valors farem un pols més a RC6.
El següent programa de prova llegeix el valor del sensor (amb la funció LlegirHX), el guarda a la variable Lectura:3 i mostra a la pantalla els tres bytes.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Lectura:3 ; Lectura del sensor Port ; Bits del port C ; RC0 a RC3 són els LED ; RC4 és DAT (DOUT del sensor) ; RC6 és CLK (PD_SCK del sensor) ; RC5 és on hi ha el brunzidor Caracter ; Caràcter o codi a enviar a la pantalla Compta ; Comptador d'iteracions D1 ; Variable unitats D2 ; Variable desenes D3 ; Variable centenes Retard1 ; Variables per als cicles de retard Retard2 Retard3 endc
org 0 Inici bsf STATUS,RP1 ; Tria el banc 2 movlw b'00000101' movwf ANSEL ; Configura AN0 i AN2 com entrada analògica clrf ANSELH ; Desactiva les altres entrades analògiques bcf STATUS,RP1 bsf STATUS,RP0 ; Tria el banc 1 movlw 0xFF ; Posa l'acumulador a FFh (tot uns) movwf TRISA ; Posa tots els bits del port A com a entrada movlw b'00010000' ; Posa RC4 com a entrada movwf TRISC ; La resta del port C és de sortida clrf TRISB ; Tot el port B és de sortida bsf TXSTA,BRGH ; Configuració de velocitat bcf BAUDCTL,BRG16 ; Paràmetre de velocitat de 8 bits movlw .25 ; Velocitat de 9600 baud movwf SPBRG ; Paràmetre de velocitat bcf TXSTA,SYNC ; Comunicació asíncrona bcf TXSTA,TX9 ; Comunicació de 8 bits bcf STATUS,RP0 ; Tria el banc 0 bsf RCSTA,SPEN ; Activa comunicació sèrie bsf STATUS,RP0 ; Tria el banc 1 bsf TXSTA,TXEN ; Activa comunicació bcf STATUS,RP0 ; Tria el banc 0 clrf Port ; Desactiva tots els bits de Port clrf PORTB ; Desactiva tots els bits del port B clrf PORTC ; Desactiva tots els bits del port C Bucle call LlegirHX ; Llegeix el valor del sensor HX711 ; Enviem l'adreça i els valors movlw .254 ; Caràcter de control movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw .1 ; Esborra la pantalla i posa el cursor a l'inici movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Lectura+2,w ; Agafem el byte més significatiu call EnviaValor ; Ho envia a la pantalla movlw ' ' ; Espai movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Lectura+1,w ; Agafem el byte intermedi call EnviaValor ; Ho envia a la pantalla movlw ' ' ; Espai movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Lectura,w ; Agafem el byte menys significatiu call EnviaValor ; Ho envia a la pantalla movlw .4 call Rets goto Bucle
; ; Llegeix el valor del sensor HX711 ; ; Lectura+2 té el byte més significatiu LlegirHX movlw .24 ; Llegim 24 bits movwf Compta ; Ho guarda a Compta bcf Port,6 ; Desactiva PD_SCK movf Port,w ; Copia Port a l'acumulador movwf PORTC ; I ho posa al PORTC BucleLec bsf Port,6 ; Activa PD_SCK movf Port,w ; Copia port a l'acumulador movwf PORTC ; I ho posa al PORTC bcf STATUS,C ; Preventivament posa C a zero btfsc PORTC,4 ; Llegeix DOUT bsf STATUS,C ; Si l'entrada està activada activem C rlf Lectura,f ; Entrem el bit a Lectura rlf Lectura+1,f ; I fem rodar els altres bits rlf Lectura+2,f bcf Port,6 ; Desactiva PD_SCK movf Port,w ; Copia Port a l'acumulador movwf PORTC ; I ho posa al PORTC nop ; Espera 3 us per fer els polsos de la mateixa amplada nop nop decfsz Compta,f ; Ja hem llegit un bit goto BucleLec ; Repetim fins tenir els 24 bsf Port,6 ; Activa PD_SCK per dir-li el guany movf Port,w ; Copia Port a l'acumulador movwf PORTC ; I ho posa al PORTC nop ; Espera 6 us per fer els polsos de la mateixa amplada nop nop nop nop nop bcf Port,6 ; Desactiva PD_SCK movf Port,w ; Copia Port a l'acumulador movwf PORTC ; I ho posa al PORTC return ; ; Envia un valor a la pantalla ; ; El valor està a W EnviaValor call BCD ; Ho converteix en BCD movlw '0' ; Per passar a ASCII, sumarem el codi de 0 addwf D3,w ; Agafa les centenes movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw '0' ; Per passar a ASCII, sumarem el codi de 0 addwf D2,w ; Agafa les desenes movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw '0' ; Per passar a ASCII, sumarem el codi de 0 addwf D1,w ; Agafa les unitats movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia return ; ; Enviem caràcters a visualitzar ; EnviaL movf Caracter,w ; Agafa el caràcter movwf TXREG ; L'envia nop nop ; Espera 2 us btfss PIR1,TXIF ; El registre TXREG ha quedat lliure? goto $-1 ; No, doncs esperem return ; Tornem al lloc des d'on hem vingut ; ; Funció de retard de 0,2 W s ; Rets movwf Retard3 Bucles decfsz Retard1,f goto Bucles decfsz Retard2,f goto Bucles decfsz Retard3,f goto Bucles return ; ; Funció que converteix un número de 8 bits a BCD (3 dígits) ; ; El valor a convertir està a W BCD clrf D3 ; Posa D3 (centenes) a zero clrf D2 ; Posa D2 (desenes) a zero movwf D1 ; Guarda W (valor a convertir) a D1 ; D1 són les unitats Cent ; Anem a trobar les centenes (D3) movlw .100 ; Carrega 100 decimal a W subwf D1,w ; Li resta W a D1 btfss STATUS,C ; Mira C i si és 1 no fa la següent ; Si és 1 vol dir resultat positiu goto Desen ; Si el resultat és negatiu les centenes ja estan ; el valor de W es perd i anem a les desenes movwf D1 ; Guarda el resultat (W) a D1 incf D3,f ; La centena restada a D1 l'afegeix a D3 goto Cent ; Tornem-ho a fer Desen ; Anem a trobar les desenes movlw .10 ; Carrega 10 decimal a W subwf D1,w ; Li resta W a D1 btfss STATUS,C ; Mira C i si és 1 no fa la següent ; Si és 1 vol dir resultat positiu goto Final ; Si el resultat és negatiu les desenes ja estan ; el valor de W es perd i anem a ASCII movwf D1 ; Guarda el resultat (W) a D1 incf D2,f ; La desena restada a D1 l'afegeix a D2 goto Desen ; Tornem-ho a fer Final retlw 0 ; Retorn amb un 0 a W end
Cada cèl·lula de càrrega i cada amplificador poden ser una mica diferents. També cada usuari pot triar en quin rang de pesos vol treballar (sempre amb un màxim absolut de 10 kg) i amb quina resolució. A títol d'exemple, anem a veure com podríem fer una aplicació.
En aquest exemple, hem suposat que el rang de mesura va de 0 a 8 kg i que volem una resolució de 5 g. Hem fet una mesura sense pes (0 kg) i una altra amb un pes proper al límit del rang i hem obtingut els següents resultats:
| Pes aplicat | Byte més significatiu (Lectura+2) |
Byte intermedi (Lectura+1) |
Byte menys significatiu (Lectura) |
Valor numèric |
| 0 g | 2 0000 0010 |
116 0111 0100 |
142 1000 1110 |
160 910 |
| 8025 g | 28 0001 1100 |
95 0101 1111 |
129 1000 0001 |
1 859 457 |
Si restem els valors de la darrera columna, trobem que per passar de 0 a 8025 g el valor ha augmentat 1 698 547 unitats. Si ho dividim pels 8025 g obtenim que cada gram ens fa augmentar el valor en 212. Per tant, cada unitat són 5 mg que és un valor massa sensible si no volem que la lectura ens estigui fluctuant constantment.
D'altra banda, si observem els bits del byte més significatiu observem que els tres primers sempre són zero. Treballar amb valors de 24 bits sembla poc raonable i, a més, ja hem vist que els bits menys significatius tenen una sensibilitat excessiva. Una possible proposta seria dividir el valor llegit per 64 i tindríem uns valors de 16 bits suficientment bons. Repetim la taula amb aquesta divisió.
| Pes aplicat | Byte més significatiu (Valor+1) |
Byte menys significatiu (Valor) |
Valor numèric |
| 0 g | 9 0000 1001 |
210 1101 0010 |
2 514 |
| 8025 g | 113 0111 0001 |
126 0111 1110 |
29 054 |
Si restem els valors de la darrera columna, trobem que per passar de 0 a 8025 g el valor ha augmentat 26540 unitats. Si ho dividim pels 8025 g obtenim que cada gram ens fa augmentar el valor en unes tres unitats. Per tant, cada unitat són 0,3 g que és un valor prou adequat.
La divisió per 64 la podríem aconseguir fent rodar sis vegades els bits cap a la dreta però és més ràpid i senzill fer-los rodar dos cops cap a l'esquerra i descartar el byte menys significatiu.
Si el que volem és obtenir el pes en grams, podríem dividir el valor per 26540 i multiplicar el resultat per 8025. Això és equivalent a multiplicar el valor per
8025 Pes [g] = Valor · ------- = Valor · 0,30237377 26540
S'ha de tenir present que el valor a utilitzar s'ha d'obtenir després d'haver restat el corresponent a l'absència de pes.
Treballant en assemblador no és fàcil dividir ni tampoc operar amb nombres reals. En canvi, sí que és fàcil dividir per valors que siguin potència de dos ja que només cal fer rodar els bits cap a la dreta. Anem a veure com quedaria aquest factor si el multipliquéssim per diferents potències de dos.
| Rotacions | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| Multiplicador | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 |
| Fracció | 0,30237377 | 0,60474755 | 1,20949510 | 2,41899020 | 4,83798040 | 9,67596081 | 19,3519216 | 38,7038432 |
| Rotacions | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| Multiplicador | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | 32768 |
| Fracció | 77,4076865 | 154,815373 | 309,630746 | 619,261492 | 1238,52298 | 2477,04596 | 4954,09193 | 9908,18387 |
Ara cal triar una de les opcions. Ens interessa una opció que no estigui molt a l'esquerra (perquè la precisió no seria molt bona) i que tingui un nombre petit després de la coma. Ja és veu que l'ideal seria agafar el cas de 13 rotacions ja és el que té un valor més petit després de la coma. Amb els casos de 14 o 15 rotacions no hi guanyem.
8025 2477 Pes [g] = Valor · ------- = Valor · ------ 26540 8192
En aquest cas, hem tingut una mica de mala sort. En altres casos, podem obtenir bons resultats amb nombres menors de rotacions.
Així doncs, podem agafar el Valor, multiplicar-lo per 2477 i dividir-lo per 8192. Per multiplicar per 2477 podríem sumar el valor amb ell mateix 2477 vegades i per dividir per 8192 caldria fer rodar els bits cap a la dreta 13 vegades (entrant zeros per l'esquerra). Ara veurem que hi ha opcions més pràctiques.
En lloc de sumar 2477 cops, podem jugar amb les potències de dos, com mostra la taula següent. Recordem que Valor l'havíem obtingut dividint Lectura per 64, per tant podem agafar aquesta variable com a base per guanyar precisió.
| Factor | Rotació teòrica a l'esquerra (sobre Valor) |
Rotació real (sobre Lectura) | ||
| Número | Sentit | |||
| 2048 | 11 | 5 | esquerra | |
| 256 | 8 | 2 | esquerra | |
| 128 | 7 | 1 | esquerra | |
| 32 | 5 | 1 | dreta | |
| 8 | 3 | 3 | dreta | |
| 4 | 2 | 4 | dreta | |
| 1 | 0 | 6 | dreta | |
| 2477 | ||||
En aquest cas tampoc hem tingut gaire sort. Altres vegades es poden fer moltes menys operacions.
Si no ens cal la variable Valor, podem prescindir d'ella. Per fer les operacions ens caldrà una variable X de 32 bits (quatre bytes) i una variable Resultat de 32 bits també.
La seqüència completa de passos seria:
Un cop fet això, ja tenim a Resultat el contingut de Valor multiplicat per 2477.
Ara hauríem de dividir per 8192, és a dir fer rodar els bits de Resultat 13 cops cap a la dreta per obtenir el Pes que serà una variable de 16 bits. El que podem fer és rodar Resultat cinc cops cap a la dreta i quedar-nos amb els dos bytes del mig. Finalment, caldria ajustar el valor de Resultat per a la resolució requerida (en el nostre exemple, 5 g).
Important: Ha de quedar clar que aquesta explicació correspon a una cèl·lula de càrrega concreta amb un amplificador determinat i, per tant, les dades llegides poden variar d'un cas a un altre. D'altra banda, cada usuari pot triar el rang de pes amb el que vol treballar (sense passar de 10 kg) i la resolució. En cada cas, doncs, els càlculs poden ser diferents.
En l'exemple explicat s'ha fet servir un pes d'aproximadament 8 kg per a les proves. Sempre és bo fer l'ajust amb el valor límit de l'escala desitjada per aconseguir la màxima precisió però no és imprescindible. Podíem haver fet l'ajust, per exemple, amb un pes al voltant de 3 kg i després haver treballat amb un rang més gran.
Observació: Existeix la possibilitat que les lectures corresponents a pesos petits siguin números negatius i que a l'arribar a un determinat pes es canviï el signe (si la cèl·lula estigués muntada amb els cables permutats també pot ser que els valors siguin majoritàriament negatius però aquest altre cas no el contemplarem perquè el raonable és muntar el circuit correctament). En el cas de tenir lectures negatives, els valors ens apareixeran codificats en complement a dos. Per tant, sabrem que el valor és negatiu si el bit 7 de Lectura+2 està activat. Amb el programa que hem presentat no ens sortirà un valor negatiu a la pantalla sinó un valor extraordinàriament gros. La taula següent mostra un exemple.
| Pes aplicat | Byte més significatiu (Lectura+2) |
Byte intermedi (Lectura+1) |
Byte menys significatiu (Lectura) |
Valor numèric | Valor pantalla |
| 0 g | 254 1111 1110 |
59 0011 1011 |
106 0110 1010 |
-115 862 | 16 661 354 |
| 574 g | 0 0000 0000 |
32 0010 0000 |
104 0110 1000 |
8 296 | 8 296 |
| 8025 g | 24 0001 1000 |
176 1011 0000 |
219 1101 1011 |
1 618 139 | 1 618 139 |
Atès que per a pesos petits tindrem lectures negatives, hem de trobar una solució que ens permeti fer els càlculs de manera senzilla. Una possible solució és sumar un valor (significativament superior a 115 862) a totes les lectures, per exemple 250 000 o, millor, 262 144 que és un valor que és potència de 2 i, per tant, facilita la feina.

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.