Mit dem Modul HX711 (erhältlich um 2-3 Euro auf ebay) lässt sich in Kombination mit einem Biegebalken (engl. load cell) und dem Arduino sehr einfach eine Digitalwaage umsetzen. Bei Verwendung eines 100g-Biegebalkens liegt die Messgenauigkeit bei 0.01g. Möchte man die Messrate erhöhen, so muss man pin-15 des HX711 mit Vcc verbinden. Dann beträgt diese 80Hz. Eine Tara-Funktion habe ich mit einem Taster umgesetzt. Betätigt man diesen, so wird der aktuelle Messwert als offset eingelesen. Dies führt dazu, dass die Anzeige jederzeit auf 0 gestellt werden kann.
Variante 1:
Bei dieser einfachen Variante kommt ein 16×2 I2C display zum Einsatz.
Arduino-Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
// ================================================================================================== // Sensor HX711 zur Auwertung eines Waagesensors mit einer Auflösung von zumindest 0,01 g // ================================================================================================== #include <LiquidCrystal_I2C.h> #include <Wire.h> LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display // Anschlüsse: // GND - GND // VCC - 5V // SDA - ANALOG Pin 4 // SCL - ANALOG pin 5 #include <HX711.h> HX711 scale(A1, A0); long Rohwert; // vom HX711 gelieferter Rohwert long offset = -115920; // offset float Scale = 6647.4; // scale float Masse; // berechnete Masse in g const int buttonPin = 2; // the number of the pushbutton pin int buttonState = 0; // variable for reading the pushbutton status // ===================== // ======= SETUP ======= // ===================== void setup() { Serial.begin(115200); scale.set_gain(128); // A-Kanal: gain = 64 oder 128; B-Kanal: fix 32 pinMode(buttonPin, INPUT); lcd.init(); // initialize the lcd // Print a message to the LCD. lcd.backlight(); lcd.setCursor(4,0); lcd.print("mg-Waage"); delay(3000); lcd.setCursor(4,0); lcd.print(" "); lcd.setCursor(0,0); lcd.print("m = "); } // ============================ // ======= HAUPTSCHLEIFE ====== // ============================ void loop() { buttonState = digitalRead(buttonPin); // button for new tara (offset) if (buttonState == HIGH) { offset = scale.read_average(20); // Einlesen von 20 Rohwerten zur Ermittlung des tara (offset) } Rohwert = scale.read_average(20); // Einlesen von 20 Rohwerten Masse = (Rohwert - offset) / Scale; // Berechnung der Masse in g /* Serial.print("Wert = "); Serial.println(Rohwert); */ Serial.print("Masse = "); Serial.println(Masse,2); lcd.setCursor(4,0); lcd.print(" "); lcd.setCursor(4,0); lcd.print(Masse,2); lcd.print(" g"); delay(50); } |
Variante 2:
Bei dieser Variante kommt anstelle des 16×2 displays ein 320×480 pixel display zum Einsatz. Damit lässt sich der Kraftverlauf F(t) graphisch darstellen. Erfasst werden bei meiner Variante rund 30 Sekunden. Der Messwert kann wieder jederzeit mittels Taster auf 0 gesetzt werden. Mit einem weiteren Taster startet man die Aufzeichnung. Im Moment ist ein 1kg-Biegebalken in Verwendung. Damit lassen sich Kräfte zwischen 0-10 N erfassen. Bei Verwendung eines anderen Biegebalkens können natürlich auch andere Bereiche erfasst werden.
Mit diesem Newtonmeter kann man einige physikalische Experimente durchführen. Zum Beispiel die Bestimmung der Oberflächenspannung mittels Ringmethode oder die Bestimmung der Haft- und Gleitreibung. Hier erkennt man schön, dass etwa die Haftreibung größer als die Gleitreibung ist und beide von der Masse/Normalkraft des zu ziehenden Objekts abhängen.
Hier die Bestimmung der Oberflächenspannung von Wasser mit der Ringmethode. Es ist darauf zu achten, den doppelten Kreisumfang in die Formel für die Oberflächenspannung σ einzusetzen, da die Oberflächenhaut sowohl auf der Ringinnenseite, als auch auf der Ringaußenseite angreift!
Ein Vergleich mit Tabellenwerten zeigt die recht gute Übereinstimmung zwischen Theorie und Experiment:
Quelle: https://de.wikipedia.org/wiki/Oberflächenspannung
Arduino-Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
#include <UTFT.h> #include <Wire.h> #include <HX711.h> HX711 scale(A1, A0); long Rohwert; // vom HX711 gelieferter Rohwert long offset = 6475; // offset float Scale = 90413; // scale: m = 17.4 g = 0.170694 N increase the value from 6475 to 21908 (difference = 15433). Therefore 1 N would increase the value by 90413 = scale float Kraft_alt, Kraft_neu; // berechnete Kraft in N float Kraft_max; // maximale Kraft // Declare which fonts we will be using extern uint8_t SmallFont[]; UTFT myGLCD(ILI9486,38,39,40,41); int i, j; // Zählvariable const int offsetPin = 2; // the number of the pushbutton pin int offsetState = 0; // variable for reading the pushbutton status const int startPin = 3; // the number of the switch pin int startState = 0; // variable for reading the switch status // ==================================== // === === // === SETUP === // === === // ==================================== void setup() { Serial.begin(9600); // while(!Serial); // time to get serial running pinMode(offsetPin, INPUT); pinMode(startPin, INPUT); // Setup the LCD myGLCD.InitLCD(); myGLCD.setFont(SmallFont); myGLCD.clrScr(); myGLCD.setColor(255, 255, 0); myGLCD.fillRect(0, 0, 479, 13); myGLCD.setColor(0, 0, 0); myGLCD.setBackColor(255, 255, 0); myGLCD.print("Newtonmeter - stoppi", CENTER, 1); scale.set_gain(128); // A-Kanal: gain = 64 oder 128; B-Kanal: fix 32 Kraft_alt = 0.0; } // ==================================== // === === // === HAUPTSCHLEIFE === // === === // ==================================== void loop() { while(startState = digitalRead(startPin)) // Warten bis start-Taster betätigt wurde { /* Rohwert = 0.0; for(j = 1; j <= 100; j++) { Rohwert = Rohwert + scale.read(); // Einlesen eines Rohwerts delay(10); } Rohwert = Rohwert / 100.0; Serial.println(Rohwert); delay(20); */ Rohwert = scale.read(); // Einlesen eines Rohwerts Kraft_neu = (Rohwert - offset) / Scale; // Berechnung der Kraft in Newton //Serial.println(Kraft_neu); myGLCD.setColor(0, 255, 0); myGLCD.setBackColor(0, 0, 0); myGLCD.print(" ", 70, 18); myGLCD.printNumF(Kraft_neu, 2, 70, 18); offsetState = digitalRead(offsetPin); // button for new tara (offset) if (offsetState == LOW) { offset = scale.read(); // Einlesen eines Rohwerts zur Ermittlung des offsets } delay(20); } Kraft_alt = 0.0; Kraft_max = 0.0; myGLCD.clrScr(); myGLCD.setColor(255, 255, 0); myGLCD.fillRect(0, 0, 479, 13); myGLCD.setColor(0, 0, 0); myGLCD.setBackColor(255, 255, 0); myGLCD.print("Newtonmeter - stoppi", CENTER, 1); // Zeichnen der beiden Achsen myGLCD.setColor(255, 255, 255); myGLCD.drawLine(50,290,430,290); myGLCD.drawLine(50,20,50,290); myGLCD.setColor(255, 255, 255); myGLCD.setBackColor(0, 0, 0); myGLCD.print("F[N]", 5, 18); myGLCD.setColor(255, 255, 255); myGLCD.setBackColor(0, 0, 0); myGLCD.print("t[sec]", 420, 300); myGLCD.setColor(255, 255, 255); myGLCD.drawLine(45,290,50,290); myGLCD.drawLine(45,240,50,240); myGLCD.drawLine(45,190,50,190); myGLCD.drawLine(45,140,50,140); myGLCD.drawLine(45,90,50,90); myGLCD.drawLine(45,40,50,40); myGLCD.drawLine(50,290,50,295); myGLCD.drawLine(100,290,100,295); myGLCD.drawLine(150,290,150,295); myGLCD.drawLine(200,290,200,295); myGLCD.drawLine(250,290,250,295); myGLCD.drawLine(300,290,300,295); myGLCD.drawLine(350,290,350,295); myGLCD.drawLine(400,290,400,295); myGLCD.setColor(255, 255, 255); myGLCD.setBackColor(0, 0, 0); myGLCD.printNumI(0,30,285); myGLCD.printNumI(2,30,235); myGLCD.printNumI(4,30,185); myGLCD.printNumI(6,30,135); myGLCD.printNumI(8,30,85); myGLCD.printNumI(10,25,35); myGLCD.printNumI(0,48,300); myGLCD.printNumI(4,98,300); myGLCD.printNumI(8,148,300); myGLCD.printNumI(12,194,300); myGLCD.printNumI(16,244,300); myGLCD.printNumI(20,294,300); myGLCD.printNumI(24,344,300); myGLCD.printNumI(28,394,300); // graues Gitternetz zeichnen myGLCD.setColor(120, 120, 120); myGLCD.drawLine(51,265,430,265); myGLCD.drawLine(51,240,430,240); myGLCD.drawLine(51,215,430,215); myGLCD.drawLine(51,190,430,190); myGLCD.drawLine(51,165,430,165); myGLCD.drawLine(51,140,430,140); myGLCD.drawLine(51,115,430,115); myGLCD.drawLine(51,90,430,90); myGLCD.drawLine(51,65,430,65); myGLCD.drawLine(51,40,430,40); myGLCD.drawLine(100,40,100,289); myGLCD.drawLine(150,40,150,289); myGLCD.drawLine(200,40,200,289); myGLCD.drawLine(250,40,250,289); myGLCD.drawLine(300,40,300,289); myGLCD.drawLine(350,40,350,289); myGLCD.drawLine(400,40,400,289); myGLCD.setColor(0, 255, 0); for(i = 1; i <= 380; i++) { offsetState = digitalRead(offsetPin); // button for new tara (offset) if (offsetState == LOW) { offset = scale.read(); // Einlesen eines Rohwerts zur Ermittlung des offsets Kraft_max = 0.0; } //Rohwert = scale.read_average(2); // Einlesen der gemittelten Rohwerten Rohwert = scale.read(); // Einlesen eines Rohwerts Kraft_neu = (Rohwert - offset) / Scale; // Berechnung der Kraft in Newton if(Kraft_neu > Kraft_max) { Kraft_max = Kraft_neu; myGLCD.setColor(255, 0, 0); myGLCD.print(" ", 180, 18); myGLCD.printNumF(Kraft_max, 3, 180, 18); myGLCD.setColor(0, 255, 0); } //Serial.println(Rohwert); myGLCD.print(" ", 70, 18); myGLCD.printNumF(Kraft_neu, 2, 70, 18); if(Kraft_neu >= 0 && Kraft_neu <= 10) { //myGLCD.drawPixel(50 + i, 290 - Kraft * 25); myGLCD.drawLine(50 + (i - 1),290 - Kraft_alt * 25,50 + i,290 - Kraft_neu * 25); Kraft_alt = Kraft_neu; } } } |