Ich arbeite momentan mit einem Arduino Mega 2560, der vier ISRs besitzt:
- drei für einen Inkrementalgeber
- einen für einen AMS8510 Batteriechip der per SPI ausgelesen wird
- ein INT für einen DCF77 Empfänger.
Meine Mega2560 Programmierung sieht wie folgt aus 1 /*
2 * aktualisiert am 2.2.2017 um 13.47
3 * Manuel Schwarz, 2017
4 *
5 */
6
7 // Includes -------------------------------------------------------
8 //AMS
9 #include <AS8510.h>
10 //Timer1
11 #include <TimerOne.h>
12 //SHT Sensor
13 #include <sht3x.h>
14 #include <sht3xanalog.h>
15 #include <shtbase.h>
16 #include <shtc1.h>
17 #include <shti2chelper.h>
18 #include <shtw1.h>
19
20 #include <Wire.h>
21 //LCD
22 #include <LiquidCrystal_I2C.h>
23 #define DCF77PIN 20
24
25 //-------------------------------------------------------------------
26
27 LiquidCrystal_I2C lcd ( 0x3F , 2 , 1 , 0 , 4 , 5 , 6 , 7 ); // 0x27 is the I2C bus address for an unmodified backpack
28
29 //Timing
30 unsigned long previousMillis0 = 0 ; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
31 unsigned long previousMillis1 = 0 ; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
32 unsigned long interval = 1000 ; // Interval zwischen zwei Änderungen
33
34 //Konstanten
35 const float Pi = 3 . 141593 ;
36 const float d = 500 . 0 ;
37
38 //Relais
39 const int relaisPin = 22 ;
40
41 //AMS Sensor
42 float voltagekorr , currentkorr ;
43
44 //Encoder
45 long incinccounter = 0 ;
46 //90 Grad Phasenverschiebung
47 long inc = 0 ;
48 int S1_SIG = 0 , S2_SIG = 1 , S3_SIG = 1 ;
49 bool firstinit = false ;
50 //Weg in m
51 float speed , distanceold , distance , distancem = 0 ;
52 //serielle Uebertragung
53 int speed_int , distance_int = 0 ;
54 int humi_int , temp_int , vin_int = 0 ;
55
56 //Speed
57 volatile byte rpmcount ;
58 unsigned int rpm ;
59 unsigned long timeold ;
60
61 //DCF77
62 int q = 0 ;
63
64 //Funktionen
65 void S3_RISE ();
66 void S2_RISE ();
67 void S1_RISE ();
68 void S3_FALL ();
69 void S2_FALL ();
70 void S1_FALL ();
71 void updateLCD ( float vin_old );
72 void serial ();
73 void timerISR ();
74 void digitalClockDisplay ();
75 void printDigits ( int digits );
76
77
78 //SHT3x
79 SHT3X sht3x ;
80
81 //Symbole LCD
82 //Charachter generator https://omerk.github.io/lcdchargen/
83 byte batteryempty [ 8 ] = {
84 0 b01110 ,
85 0 b11011 ,
86 0 b10001 ,
87 0 b10001 ,
88 0 b10001 ,
89 0 b10001 ,
90 0 b10001 ,
91 0 b11111
92 };
93 byte battery25 [ 8 ] = {
94 0 b01110 ,
95 0 b11011 ,
96 0 b10001 ,
97 0 b10001 ,
98 0 b10001 ,
99 0 b11111 ,
100 0 b11111 ,
101 0 b11111
102 };
103 byte battery100 [ 8 ] = {
104 0 b01110 ,
105 0 b11111 ,
106 0 b11111 ,
107 0 b11111 ,
108 0 b11111 ,
109 0 b11111 ,
110 0 b11111 ,
111 0 b11111
112 };
113 byte distancesymbol [ 8 ] = {
114 0 b00000 ,
115 0 b00000 ,
116 0 b10001 ,
117 0 b11111 ,
118 0 b10001 ,
119 0 b00000 ,
120 0 b00000 ,
121 0 b00000
122 };
123 byte arrowright [ 8 ] = {
124 0 b00000 ,
125 0 b01000 ,
126 0 b01100 ,
127 0 b01110 ,
128 0 b01111 ,
129 0 b01110 ,
130 0 b01100 ,
131 0 b01000
132 };
133
134
135
136 void setup ()
137 {
138 Serial . begin ( 9600 );
139 delay ( 300 );
140 // while the serial stream is not open, do nothing
141 while ( ! Serial );
142
143 //pinMode(DCF77PIN, INPUT);
144
145 // activate LCD module
146 lcd . begin ( 20 , 4 ); // for 16 x 2 LCD module
147 lcd . setBacklightPin ( 3 , POSITIVE );
148 lcd . setBacklight ( HIGH );
149 //Display Start
150 lcd . home (); // set cursor to 0,0
151 //ASCII Umlaute verwenden
152 lcd . print ( "xx" );
153 lcd . setCursor ( 0 , 1 ); // go to start of 2nd line
154 lcd . print ( "xx" );
155 lcd . setCursor ( 0 , 2 ); // go to start of 2nd line
156 lcd . print ( " " );
157 lcd . setCursor ( 0 , 3 ); // go to start of 2nd line
158 lcd . print ( "Version 0.5" );
159
160 //PINBELEGUNG AS8510 Board
161 //vom Shunt gesehen linke Seite
162 // Board / AtMega2560
163 // GND GND
164 // I07 53
165 // I02 3
166 // I01 1/TX0
167
168 // start the AS8510 library:
169 AS8510 . begin ();
170 AS8510 . set_volt_calib ( 1167 ); //use to fine trim voltage measurement
171 AS8510 . set_curr_calib ( 1060 ); //use to fine trim current measurement
172
173 AS8510 . set_curr_gain ( 40 ); //possible gain values 1,5,25,40,100
174 AS8510 . autoconversion ();
175
176 // give the sensor time to set up:
177 delay ( 100 );
178
179 // INKREMENTALFGEBER
180 // Versorgungsspannung: +5 VDC ---> braun/grün
181 // GND ---> weiss/grün
182 //
183 //Geschwindigkeitsmessung
184 rpmcount = 0 ;
185 rpm = 0 ;
186 timeold = 0 ;
187
188 Timer1 . initialize ( 1000000 ); // Setze Timer auf 1sec
189 //Time1 aktivieren
190 //Timer1.attachInterrupt(timerISR);
191
192 //*********incinccounter inkrementieren oder dekrementieren -> ISR aktivieren
193 //INT1 - PIN3 / EMS INT
194 //----------------------
195 //INT0 - PIN2 / A
196 //INT5 - PIN18 / B
197 //INT4 - PIN19 / Z
198 //----------------------
199 //INT3 - PIN20 / DCF77
200 //INT2 - PIN21 / NN
201
202 //INT1 (Pin 3) wird von AMS genutzt!
203 //INT0 - PIN 2 (mega 2560) / A-Signal / braun
204 attachInterrupt ( 0 , S1_RISE , RISING );
205 //INT5 - PIN 18 (mega 2560) / B-Signal / grau
206 attachInterrupt ( 5 , S2_RISE , RISING );
207 //INT4 - PIN 19 (mega 2560) / Z-Signal / rot
208 attachInterrupt ( 4 , S3_RISE , RISING );
209
210
211 //eigene Chars
212 lcd . createChar ( 0 , batteryempty );
213 lcd . createChar ( 1 , battery25 );
214 lcd . createChar ( 2 , distancesymbol );
215 lcd . createChar ( 3 , arrowright );
216 }
217
218 void timerISR ()
219 {
220 Timer1 . detachInterrupt (); //stoppe den Timer
221 distance = distancem ;
222 speed = ( distance - distanceold );
223 //Serial.print("Geschwindigkeit: ");
224 //Serial.print(speed,3); Serial.print(",");
225 //Serial.print(distance,3); Serial.print(",");
226 //Serial.print(distanceold,3); Serial.print(",");
227
228 distanceold = distance ;
229 Timer1 . attachInterrupt ( timerISR ); //starte den Timer
230 }
231
232 void loop (){
233 //AMS Daten
234 voltagekorr = ( AS8510 . read_voltage () * 2 . 2403 ) - 12 . 518 ;
235 currentkorr = ( AS8510 . read_current () * 9 . 4487 ) - 0 . 0035 ;
236
237 //Umfang Messrad 500mm
238 //90 Grad Phasenverschiebung
239 //Inkremente
240 inc = incinccounter / 4 ;
241 //zurueckgelegter Weg
242 distancem = (( float ) inc / 1000 );
243
244 //INTEGER
245 distance_int = distancem * 1000 ;
246 speed_int = speed * 100 ;
247 humi_int = sht3x . getHumidity () * 100 ;
248 temp_int = sht3x . getTemperature () * 100 ;
249
250 //Restart the interrupt processing
251 //INT0 - pin2 (mega 2560) / A-Signal / braun
252 //attachInterrupt(4, S1_RISE, RISING);
253 //INT1 - pin 3 (mega 2560) / B-Signal / grau
254 //attachInterrupt(3, S2_RISE, RISING);
255 //INT2 - pin 21 (mega 2560) / Z-Signal / rot
256 //attachInterrupt(2, S3_RISE, RISING);
257
258 sht3x . readSample ();
259 //Führe eine Messung über 10 Impulse aus, ein Impuls dauert genau eine Sekunde
260 //q = DCF77signalQuality(10);
261
262 //if (millis() - previousMillis0 > interval) {
263 //previousMillis0 = millis(); // aktuelle Zeit abspeichern
264 // updateLCD(vin_old);
265 //}
266 if ( millis () - previousMillis1 > 1 ) {
267 previousMillis1 = millis (); // aktuelle Zeit abspeichern
268 serial ();
269 }
270 }
271
272
273 //****************************************************************************************************
274 // Quadratur Modulation
275 //
276
277 //Phase | Rotation im Uhrzeigersinn | Rotation gegen den Uhrzeigersinn
278 //- A B A B
279 //1 0 0 1 0
280 //2 0 1 1 1
281 //3 1 1 0 1
282 //4 1 0 0 0
283
284 void S1_RISE (){
285 detachInterrupt ( 4 );
286 S1_SIG = 1 ;
287
288 if ( S2_SIG == 0 )
289 incinccounter ++ ; //entry
290 if ( S2_SIG == 1 )
291 incinccounter -- ; //exit
292 //Serial.println(incinccounter);
293 attachInterrupt ( 0 , S1_FALL , FALLING );
294 }
295
296 void S1_FALL (){
297 detachInterrupt ( 0 );
298 S1_SIG = 0 ;
299
300 if ( S2_SIG == 1 )
301 incinccounter ++ ; //entry
302 if ( S2_SIG == 0 )
303 incinccounter -- ; //exit
304 //Serial.println(incinccounter);
305 attachInterrupt ( 0 , S1_RISE , RISING );
306 }
307
308 void S2_RISE (){
309 detachInterrupt ( 5 );
310 S2_SIG = 1 ;
311
312 if ( S1_SIG == 1 )
313 incinccounter ++ ;
314 if ( S1_SIG == 0 )
315 incinccounter -- ; //exit
316 //Serial.println(incinccounter);
317 attachInterrupt ( 5 , S2_FALL , FALLING );
318 }
319
320 void S2_FALL (){
321 detachInterrupt ( 5 );
322 S2_SIG = 0 ;
323
324 if ( S1_SIG == 0 )
325 incinccounter ++ ; //entry
326 if ( S1_SIG == 1 )
327 incinccounter -- ;
328 //inc=incinccounter/4;
329 //turns=(incinccounter/500);
330 //Serial.println(incinccounter);
331 attachInterrupt ( 5 , S2_RISE , RISING );
332 }
333
334 void S3_RISE (){
335 S3_SIG = 1 ;
336 detachInterrupt ( 4 );
337
338 if ( ! firstinit && (( S2_SIG == 1 && S1_SIG == 1 ) || ( S1_SIG == 0 && S2_SIG == 1 )))
339 {
340 incinccounter = 0 ;
341 firstinit = true ;
342 }
343 attachInterrupt ( 4 , S3_FALL , FALLING );
344 }
345
346 void S3_FALL (){
347 S3_SIG = 0 ;
348 detachInterrupt ( 4 );
349
350 if ( ! firstinit && (( S2_SIG == 1 && S1_SIG == 1 ) || ( S1_SIG == 1 && S2_SIG == 0 )))
351 {
352 incinccounter = 0 ;
353 firstinit = true ;
354 }
355 attachInterrupt ( 4 , S3_RISE , RISING );
356 }
357 // Ende der Quadratur Modulation
358 //****************************************************************************************************
359
360 void updateLCD ( float vin_old ){
361 lcd . clear ();
362 lcd . home (); // set cursor to 0,0
363 lcd . print ( "U_Bat: " );
364 lcd . print ( voltagekorr , 3 );
365 lcd . print ( " V " );
366 lcd . print ( "I_Bat: " );
367 lcd . print ( currentkorr , 3 );
368 lcd . print ( " A " );
369
370 //display battery state symbol
371 lcd . write (( uint8_t ) 1 );
372
373 //show distance
374 lcd . setCursor ( 0 , 1 ); // go to start of 2nd line
375 lcd . write (( uint8_t ) 2 );
376 lcd . print ( " " );
377 lcd . print ( inc );
378 lcd . print ( " mm " );
379
380 lcd . print ( distancem , 2 );
381 lcd . print ( " m " );
382
383 lcd . setCursor ( 0 , 2 ); // go to start of 2nd line
384 lcd . print ( "v= " );
385 lcd . print ( speed );
386 lcd . print ( " m/s " );
387
388 //Temp-LF
389 lcd . setCursor ( 0 , 3 ); // go to start of 3rd line
390 lcd . print ( sht3x . getHumidity (), 2 );
391 lcd . print ( " % " );
392 lcd . write (( uint8_t ) 3 );
393 lcd . print ( " " );
394 lcd . print ( sht3x . getTemperature (), 2 );
395
396 //Character Grad 11011111
397 lcd . print ( " " );
398 lcd . write ( 0 b11011111 );
399 lcd . print ( "C " );
400 }
401
402 void serial (){
403 //NUR INT AUSGEBEN!!!!
404 //Auswertung in Python
405 //distancem;speed;v_in;humidty;temperature
406 //Serial.print(distance,3); Serial.print(";");
407 Serial . print ( humi_int , DEC ); Serial . print ( ";" );
408 Serial . print ( temp_int , DEC ); Serial . print ( ";" );
409 //Serial.print(vin_int); Serial.print(";");
410 //Serial.print(current); Serial.print(";");
411 //Serial.print(distance_int); Serial.print(";");
412 Serial . print ( speed_int , DEC ); Serial . print ( ";" ); Serial . print ( " \n\r " );
413
414
415 Serial . print ( "INC= " );
416 Serial . print ( incinccounter );
417 Serial . print ( " \r \n " );
418 Serial . print ( "x[m]= " );
419 Serial . println ( distancem );
420 Serial . print ( " \r \n " );
421 //SHT3x
422 Serial . print ( "SHT3x: " );
423 Serial . print ( "RH: " );
424 Serial . print ( sht3x . getHumidity (), 2 );
425 Serial . print ( " % \r \n " );
426 Serial . print ( "T: " );
427 Serial . print ( sht3x . getTemperature (), 2 );
428 Serial . print ( " Grad Celsius \r \n " );
429
430 //Wenn kein Wechsel zwischen HIGH und LOW am Anschluss erkannt wurde
431 //bedeutet das in 99,99% aller Fälle das der DCF Empfänger nicht arbeitet
432 //denn bei extrem schlechten Empfang hat man Wechsel, nur kann man sie nicht auswerten.
433 //if (!q) {Serial.print("# (Schaltung pruefen!)");}
434
435 //for (int i = 0; i < q; i++) {
436 // Serial.print(">");
437 //}
438 //Serial.println("");
439 }
440
441 int DCF77signalQuality ( int pulses ) {
442 int prevSensorValue = 0 ;
443 unsigned long loopTime = 10000 ; //Impuls Länge genau eine Sekunde
444 //Da wir ja mitten in einem Impuls einsteigen könnten, verwerfen wir den ersten.
445 int rounds = - 1 ;
446 unsigned long gagingStart = 0 ;
447 unsigned long waitingPeriod = 0 ;
448 int overallChange = 0 ;
449 int change = 0 ;
450
451 while ( true ) {
452 //Unsere Schleife soll das Eingangssignal (LOW oder HIGH) 10 mal pro
453 //Sekunde messen um das sicherzustellen, messen wir dessen Ausführungszeit.
454 gagingStart = micros ();
455 int sensorValue = digitalRead ( DCF77PIN );
456 //Wenn von LOW nach HIGH gewechselt wird beginnt ein neuer Impuls
457 if ( sensorValue == 1 && prevSensorValue == 0 ) {
458 rounds ++ ;
459 if ( rounds > 0 && rounds < pulses + 1 ) { overallChange += change ;}
460 if ( rounds == pulses ) { return overallChange / pulses ;}
461 change = 0 ;
462 }
463 prevSensorValue = sensorValue ;
464 change ++ ;
465
466 //Ein Wechsel zwichen LOW und HIGH müsste genau alle 100 Durchläufe stattfinden
467 //wird er größer haben wir kein Empfang
468 //300 habe ich als guten Wert ermittelt, ein höherer Wert würde die Aussage festigen
469 //erhöht dann aber die Zeit.
470 if ( change > 300 ) { return 0 ;}
471 //Berechnen und anpassen der Ausführungszeit
472 waitingPeriod = loopTime - ( micros () - gagingStart );
473 delayMicroseconds ( waitingPeriod );
474 }
475 }
Die AS8510 Library: 1 #include "pins_arduino.h"
2 #include "AS8510.h"
3
4 volatile float voltage , current ;
5 AS8510Class AS8510 ;
6
7 AS8510Class :: AS8510Class ()
8 {
9 current = 0 ;
10 voltage = 0 ;
11 curr_calib = 2635 ;
12 volt_calib = 1160 ;
13
14 }
15
16 void AS8510Class :: begin () {
17
18 // start the SPI library:
19 // Set SS to high so a connected chip will be "deselected" by default
20 digitalWrite ( SS , HIGH );
21
22 // When the SS pin is set as OUTPUT, it can be used as
23 // a general purpose output port (it doesn't influence
24 // SPI operations).
25 // initalize the data ready and chip select pins:
26 pinMode ( SS , OUTPUT );
27 pinMode ( INT_PIN , INPUT );
28 pinMode ( CS_PIN , OUTPUT );
29
30 // Warning: if the SS pin ever becomes a LOW INPUT then SPI
31 // automatically switches to Slave, so the data direction of
32 // the SS pin MUST be kept as OUTPUT.
33 SPCR |= _BV ( MSTR );
34 SPCR |= _BV ( SPE );
35
36 // Set direction register for SCK and MOSI pin.
37 // MISO pin automatically overrides to INPUT.
38 // By doing this AFTER enabling SPI, we avoid accidentally
39 // clocking in a single bit since the lines go directly
40 // from "input" to SPI control.
41 // http://code.google.com/p/arduino/issues/detail?id=888
42 #ifdef __AVR__
43 pinMode ( SCK , OUTPUT );
44 pinMode ( MOSI , OUTPUT );
45 #endif
46
47 SPCR = ( SPCR & ~ SPI_MODE_MASK ) | SPI_MODE3 ;
48 SPCR = ( SPCR & ~ SPI_CLOCK_MASK ) | ( SPI_CLOCK_DIV8 & SPI_CLOCK_MASK );
49 SPSR = ( SPSR & ~ SPI_2XCLOCK_MASK ) | (( SPI_CLOCK_DIV8 >> 2 ) & SPI_2XCLOCK_MASK );
50
51 AS8510 . config ();
52 }
53 //INT1 - PIN3 / EMS INT
54 void AS8510Class :: autoconversion ()
55 {
56 //EICRA |= (1 << ISC00)|(1 << ISC01); // set INT0 to trigger on rising edge
57 EICRA |= ( 1 << ISC10 ) | ( 1 << ISC11 ); // set INT1 to trigger on rising edge
58 //EIMSK |= (1 << INT0); // Turns on INT0
59 EICRA |= ( 1 << INT1 ); // Turns on INT1
60 AS8510 . start ();
61 }
62
63 ISR ( INT1_vect )
64 {
65 unsigned char reg [ 4 ];
66 AS8510 . spird4 ( 0 , & reg [ 0 ]); //read the four bits of voltage 1 and 2
67
68 current = (( reg [ 0 ] << 8 ) | reg [ 1 ]);
69 voltage = (( reg [ 2 ] << 8 ) | reg [ 3 ]);
70 }
71
72
73 void AS8510Class :: config ()
74 {
75 AS8510 . spiwr ( RESET_REG , 0 ); //reset
76 delay ( 50 );
77
78 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_40 );
79 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
80
81 AS8510 . spiwr ( PD_CTL_REG_3 , 0xFC ); //output in 2's complement
82 AS8510 . spiwr ( ACH_CTL_REG , ETR );
83
84 #ifdef FAST_ACQ
85 AS8510 . spiwr ( DEC_REG_R1_I , 0x4B ); // CIC1-64, Chop-CLK=2K, CIC2-4, ( SDM clock = 1MHz )
86 AS8510 . spiwr ( DEC_REG_R1_V , 0x4B ); // CIC1-64, Chop-CLK=2K, CIC2-4, ( SDM clock = 1MHz )
87 #else
88 AS8510 . spiwr ( DEC_REG_R1_I , 0x4F ); // CIC1-64, Chop-CLK=2K, CIC2-128, ( SDM clock = 1MHz )
89 AS8510 . spiwr ( DEC_REG_R1_V , 0x4F ); // CIC1-64, Chop-CLK=2K, CIC2-128, ( SDM clock = 1MHz )
90 #endif
91 }
92
93 void AS8510Class :: set_curr_gain ( unsigned char gain )
94 {
95 switch ( gain )
96 {
97 case 1 :
98 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA | BYPASS_CURRENT_PGA );
99 break ;
100 case 5 :
101 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_5 );
102 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
103 break ;
104 case 25 :
105 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_25 );
106 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
107 break ;
108 case 40 :
109 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_40 );
110 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
111 break ;
112 case 100 :
113 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_100 );
114 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
115 break ;
116 default:
117 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_40 );
118 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
119 break ;
120 }
121 }
122
123 void AS8510Class :: getvoltage2 ( float * v , float * i )
124 {
125 unsigned char reg [ 4 ];
126 AS8510 . spird4 ( 0 , & reg [ 0 ]); //read the four bits of voltage 1 and 2
127
128 * i = (( reg [ 0 ] << 8 ) | reg [ 1 ]) / curr_calib ;
129 * v = (( reg [ 2 ] << 8 ) | reg [ 3 ]) / volt_calib ;
130 }
131
132
133 void AS8510Class :: start ()
134 {
135 AS8510 . spiwr ( 0x0A , AS8510 . spird ( 0x0A ) | 0x01 ); //set start bit
136 }
137
138 void AS8510Class :: end ()
139 {
140 AS8510 . spiwr ( 0x0A , AS8510 . spird ( 0x0A ) & 0xFE ); //clear start bit
141 }
142
143 // writing of one data byte at Adr0
144 void AS8510Class :: spiwr ( unsigned char addr , unsigned char data )
145 {
146 // take the chip select low to select the device:
147 digitalWrite ( CS_PIN , LOW );
148
149 SPDR = addr & 0x7F ; //Send register location
150 while ( ! ( SPSR & _BV ( SPIF )));
151 SPDR = data ; //Send value to record into register
152 while ( ! ( SPSR & _BV ( SPIF )));
153
154 // take the chip select high to de-select:
155 digitalWrite ( CS_PIN , HIGH );
156 }
157
158 // reading of one data byte from Adr0 into DataIn[0]
159 unsigned char AS8510Class :: spird ( unsigned char addr )
160 {
161 unsigned char dat ;
162 // take the chip select low to select the device:
163 digitalWrite ( CS_PIN , LOW );
164
165 SPDR = addr | 0x80 ; //Send register location and read
166 while ( ! ( SPSR & _BV ( SPIF )));
167 SPDR = 0xFF ;
168 while ( ! ( SPSR & _BV ( SPIF ))); //Read value
169 dat = SPDR ;
170
171 // take the chip select high to de-select:
172 digitalWrite ( CS_PIN , HIGH );
173
174 return dat ;
175 }
176
177 // reading of four data bytes beginning from Adr0 into DataIn[0..3]
178 void AS8510Class :: spird4 ( unsigned char addr , unsigned char * DataIn )
179 {
180 unsigned char i ;
181
182 // take the chip select low to select the device:
183 digitalWrite ( CS_PIN , LOW );
184
185 SPDR = addr | 0x80 ; //Send register location and read
186 while ( ! ( SPSR & _BV ( SPIF )));
187
188 for ( i = 0 ; i < 4 ; i ++ )
189 {
190 SPDR = 0xFF ;
191 while ( ! ( SPSR & _BV ( SPIF ))); //Read value
192 DataIn [ i ] = SPDR ;
193 }
194
195 // take the chip select high to de-select:
196 digitalWrite ( CS_PIN , HIGH );
197
198 }
1 #ifndef _AS8510_H_INCLUDED
2 #define _AS8510_H_INCLUDED
3
4 #include <stdio.h>
5 #include <Arduino.h>
6 #include <avr/pgmspace.h>
7
8 #define DREG_I1 0x00
9 #define DREG_I2 0x01
10 #define DREG_V1 0x02
11 #define DREG_V2 0x03
12 #define STATUS_REG 0x04
13 #define DEC_REG_R1_I 0x05
14 #define DEC_REG_R2_I 0x06
15 #define FIR_CTL_REG_I 0x07
16 #define CLK_REG 0x08
17 #define RESET_REG 0x09
18 #define MOD_CTL_REG 0x0A
19 #define MOD_TA_REG1 0x0B
20 #define MOD_TA_REG2 0x0C
21 #define MOD_ITH_REG1 0x0D
22 #define MOD_ITH_REG2 0x0E
23 #define MOD_TMC_REG1 0x0F
24 #define MOD_TMC_REG2 0x10
25 #define NOM_ITH_REG1 0x11
26 #define NOM_ITH_REG2 0x12
27 #define PGA_CTL_REG 0x13
28 #define PD_CTL_REG_1 0x14
29 #define PD_CTL_REG_2 0x15
30 #define PD_CTL_REG_3 0x16
31 #define ACH_CTL_REG 0x17
32 #define ISC_CTL_REG 0x18
33 #define OTP_EN_REG 0x19
34 #define OTP_REG_0 0x25
35 #define OTP_REG_1 0x26
36 #define OTP_REG_2 0x27
37 #define STATUS_REG_2 0x44
38 #define DEC_REG_R1_V 0x45
39 #define DEC_REG_R2_V 0x46
40 #define FIR_CTL_REG_V 0x47
41
42 #define CURRENT_GAIN_5 0x00
43 #define CURRENT_GAIN_25 0x40
44 #define CURRENT_GAIN_40 0x80
45 #define CURRENT_GAIN_100 0xC0
46
47 #define BYPASS_VOLTAGE_PGA 0xF7
48 #define BYPASS_CURRENT_PGA 0xFB
49
50
51
52 #define SPI_CLOCK_DIV4 0x00
53 #define SPI_CLOCK_DIV16 0x01
54 #define SPI_CLOCK_DIV64 0x02
55 #define SPI_CLOCK_DIV128 0x03
56 #define SPI_CLOCK_DIV2 0x04
57 #define SPI_CLOCK_DIV8 0x05
58 #define SPI_CLOCK_DIV32 0x06
59
60 #define SPI_MODE0 0x00
61 #define SPI_MODE1 0x04
62 #define SPI_MODE2 0x08
63 #define SPI_MODE3 0x0C
64
65 #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
66 #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
67 #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
68
69 #define CS_PIN 10
70 #define INT_PIN 3
71
72 class AS8510Class {
73 public:
74 AS8510Class ();
75 static void begin (); // Default
76 void autoconversion ();
77 static void config ();
78 static void set_curr_gain ( unsigned char gain );
79 void getvoltage2 ( float * v , float * i );
80 static void start ();
81 static void end ();
82 inline void set_curr_calib ( float calib );
83 inline void set_volt_calib ( float calib );
84 inline float read_voltage ();
85 inline float read_current ();
86 void spiwr ( unsigned char addr , unsigned char data );
87 unsigned char spird ( unsigned char addr );
88 void spird4 ( unsigned char addr , unsigned char * DataIn );
89
90 private:
91 float curr_calib , volt_calib ;
92
93 };
94
95 extern volatile float voltage , current ;
96 extern AS8510Class AS8510 ;
97
98 void AS8510Class :: set_volt_calib ( float calib )
99 {
100 volt_calib = calib ;
101 }
102
103 void AS8510Class :: set_curr_calib ( float calib )
104 {
105 curr_calib = calib ;
106 }
107
108 float AS8510Class :: read_voltage ()
109 {
110 return ( getvoltage2 / volt_calib );
111 }
112
113 float AS8510Class :: read_current ()
114 {
115 return ( current / curr_calib );
116 }
117
118 #endif
Der Compiler wirft immer die Fehlermitteilung:
WInterrupts.c.o (symbol from plugin): In function `attachInterrupt'
(.text+0x0): multiple definition of `__vector_6'
libraries\AS8510\AS8510.cpp.o (symbol from plugin):(.text+0x0): first
defined here
Ich habe bereits in der Vector Tabelle vom Atmel Datenblatt
nachgeschaut, aber finde keine Überschneidung der Interrupt
Serviceroutine in der CPP Library mit dem Hauptprogramm.
Wäre super, wenn mir jemand einen Denkanstoß geben könnte.
Danke.
Zwischen den AS8510 Funktionen versteckt sich ein
1 ISR ( INT1_vect )
2 {
3 unsigned char reg [ 4 ];
4 AS8510 . spird4 ( 0 , & reg [ 0 ]); //read the four bits of voltage 1 and 2
5
6 current = (( reg [ 0 ] << 8 ) | reg [ 1 ]);
7 voltage = (( reg [ 2 ] << 8 ) | reg [ 3 ]);
8 }
Vermutlich ist der noch woanders definiert.
also der INT1 ist nicht zweimal belegt im Code.
Vector_6 muss auch irgendetwas mit INT3 zu tun haben - siehe Anhang
von
Lothar M.
(Firma: Titel)
(lkmiller )
(Moderator )
07.02.2017 15:24
Manuel S. schrieb:
> Vector_6 muss auch irgendetwas mit INT3 zu tun haben - siehe Anhang
Oder gar dem abgeschnittenen INT4...
Manuel S. schrieb:
> Ich arbeite momentan mit einem Arduino Mega 2560, der vier ISRs besitzt:
> - drei für einen Inkrementalgeber
> - einen für einen AMS8510 Batteriechip der per SPI ausgelesen wird
> - ein INT für einen DCF77 Empfänger.
Ein Wort zu diesem Konzept: wer Interrupts kennt, der pollt.
Manuel S. schrieb:
> Der Compiler wirft immer die Fehlermitteilung: ...
Und sonst nichts? Warnungen?
Lothar M. schrieb:
> Manuel S. schrieb:
>> Vector_6 muss auch irgendetwas mit INT3 zu tun haben - siehe Anhang
> Oder gar dem abgeschnittenen INT4...
>
> Manuel S. schrieb:
>> Ich arbeite momentan mit einem Arduino Mega 2560, der vier ISRs besitzt:
>> - drei für einen Inkrementalgeber
>> - einen für einen AMS8510 Batteriechip der per SPI ausgelesen wird
>> - ein INT für einen DCF77 Empfänger.
> Ein Wort zu diesem Konzept: wer Interrupts kennt, der pollt.
>
> Manuel S. schrieb:
>> Der Compiler wirft immer die Fehlermitteilung: ...
> Und sonst nichts? Warnungen?
Die abgeschnittene Tabelle habe ich nochmal vollständig angehängt, bei
den vector Beschriftungen muss man doch im Atmel Datenblatt immer -1
nehmen.
Also bei '__vector_6' dann Vektor 5?
> Ein Wort zu diesem Konzept: wer Interrupts kennt, der pollt.
>
Ein Polling kann ich nicht verwenden, da der Inkrementalgeber nur kurze
steigende Taktflanken ausgibt. Deswegen arbeite ich mit einer ISR, um
das zuverlässig zu erkennen.
> Und sonst nichts? Warnungen?
Die komplette Fehlermeldung habe ich nochmal angehängt.
von
Yalu X.
(yalu )
(Moderator )
07.02.2017 15:52
Beim Arduino sind alle externen Interrupts durch die Laufzeitumgebung
bereits belegt. Deswegen kannst du einen Interrupthandler nicht mit
definieren. Nimm stattdessen die Funktion attachInterrupt(), wie du es
an anderer Stelle auch schon getan hast.
Warum der Linker __vector_6 und nicht den zu INT1_vect gehörenden
__vector_2 anmeckert, verstehe ich allerdings auch nicht ganz.
__vector_6 gehört eigentlich zu INT5_vect. Bist du sicher, dass die
gepostete Codeversion exakt dieselbe ist, für die auch der angegebene
Fehler ausgegeben wurde?
Manuel S. schrieb:
> Ein Polling kann ich nicht verwenden, da der Inkrementalgeber nur kurze
> steigende Taktflanken ausgibt. Deswegen arbeite ich mit einer ISR, um
> das zuverlässig zu erkennen.
Das ist ein Trugschluss: Gerade die interruptbasierte Auswertung von
Encodern reagiert empfindlich auf Zappeln an den Signalflanken. Bei
Verfahren mit Polling tritt dieses Problem nicht auf. Natürlich muss die
Polling-Frequenz der maximalen Drehzahl des Encoders angepasst werden,
damit keine Impulse verloren gehen. Dazu gibt es hier im Forum aber
schon zig Diskussionen. Auch in der Artikelsammlung wurde dieses Thema
schon erörtert.
@Yalu danke für den Hinweis.
Ich habe den Code umgebaut, jetzt meckert aber der Compiler dass er die
eine Funktion der Klasse nicht findet.
'class AS8510Class' has no member named 'ams'
Im Header File ist die Member function eigentlich bekannt... 1
2 /*
3 * aktualisiert am 2.2.2017 um 13.47
4 * Manuel Schwarz, 2017
5 * TÜV Süd
6 */
7
8 // Includes -------------------------------------------------------
9 //AMS
10 #include <AS8510.h>
11 //Timer1
12 #include <TimerOne.h>
13 //SHT Sensor
14 #include <sht3x.h>
15 #include <sht3xanalog.h>
16 #include <shtbase.h>
17 #include <shtc1.h>
18 #include <shti2chelper.h>
19 #include <shtw1.h>
20
21 #include <Wire.h>
22 //LCD
23 #include <LiquidCrystal_I2C.h>
24 #define DCF77PIN 23
25
26 //-------------------------------------------------------------------
27
28 LiquidCrystal_I2C lcd ( 0x3F , 2 , 1 , 0 , 4 , 5 , 6 , 7 ); // 0x27 is the I2C bus address for an unmodified backpack
29
30 //Timing
31 unsigned long previousMillis0 = 0 ; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
32 unsigned long previousMillis1 = 0 ; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
33 unsigned long interval = 1000 ; // Interval zwischen zwei Änderungen
34
35 //Konstanten
36 const float Pi = 3 . 141593 ;
37 const float d = 500 . 0 ;
38
39 //Relais
40 const int relaisPin = 22 ;
41
42 //AMS Sensor
43 float voltagekorr , currentkorr ;
44
45 //Encoder
46 long incinccounter = 0 ;
47 //90 Grad Phasenverschiebung
48 long inc = 0 ;
49 int S1_SIG = 0 , S2_SIG = 1 , S3_SIG = 1 ;
50 bool firstinit = false ;
51 //Weg in m
52 float speed , distanceold , distance , distancem = 0 ;
53 //serielle Uebertragung
54 int speed_int , distance_int = 0 ;
55 int humi_int , temp_int , vin_int = 0 ;
56
57 //Speed
58 volatile byte rpmcount ;
59 unsigned int rpm ;
60 unsigned long timeold ;
61
62 //DCF77
63 int q = 0 ;
64
65 //Funktionen
66 void S3_RISE ();
67 void S2_RISE ();
68 void S1_RISE ();
69 void S3_FALL ();
70 void S2_FALL ();
71 void S1_FALL ();
72 void updateLCD ( float vin_old );
73 void serial ();
74 void timerISR ();
75 void digitalClockDisplay ();
76 void printDigits ( int digits );
77
78
79 //SHT3x
80 SHT3X sht3x ;
81
82 //Symbole LCD
83 //Charachter generator https://omerk.github.io/lcdchargen/
84 byte batteryempty [ 8 ] = {
85 0 b01110 ,
86 0 b11011 ,
87 0 b10001 ,
88 0 b10001 ,
89 0 b10001 ,
90 0 b10001 ,
91 0 b10001 ,
92 0 b11111
93 };
94 byte battery25 [ 8 ] = {
95 0 b01110 ,
96 0 b11011 ,
97 0 b10001 ,
98 0 b10001 ,
99 0 b10001 ,
100 0 b11111 ,
101 0 b11111 ,
102 0 b11111
103 };
104 byte battery100 [ 8 ] = {
105 0 b01110 ,
106 0 b11111 ,
107 0 b11111 ,
108 0 b11111 ,
109 0 b11111 ,
110 0 b11111 ,
111 0 b11111 ,
112 0 b11111
113 };
114 byte distancesymbol [ 8 ] = {
115 0 b00000 ,
116 0 b00000 ,
117 0 b10001 ,
118 0 b11111 ,
119 0 b10001 ,
120 0 b00000 ,
121 0 b00000 ,
122 0 b00000
123 };
124 byte arrowright [ 8 ] = {
125 0 b00000 ,
126 0 b01000 ,
127 0 b01100 ,
128 0 b01110 ,
129 0 b01111 ,
130 0 b01110 ,
131 0 b01100 ,
132 0 b01000
133 };
134
135
136
137 void setup ()
138 {
139 Serial . begin ( 9600 );
140 delay ( 300 );
141 // while the serial stream is not open, do nothing
142 while ( ! Serial );
143
144 //pinMode(DCF77PIN, INPUT);
145
146 // activate LCD module
147 lcd . begin ( 20 , 4 ); // for 16 x 2 LCD module
148 lcd . setBacklightPin ( 3 , POSITIVE );
149 lcd . setBacklight ( HIGH );
150 //Display Start
151 lcd . home (); // set cursor to 0,0
152 //ASCII Umlaute verwenden
153 lcd . print ( "T \365 v S \365 d" );
154 lcd . setCursor ( 0 , 1 ); // go to start of 2nd line
155 lcd . print ( "Product Service" );
156 lcd . setCursor ( 0 , 2 ); // go to start of 2nd line
157 lcd . print ( " " );
158 lcd . setCursor ( 0 , 3 ); // go to start of 2nd line
159 lcd . print ( "Version 0.5" );
160
161 //PINBELEGUNG AS8510 Board
162 //vom Shunt gesehen linke Seite
163 // Board / AtMega2560
164 // GND GND
165 // I07 53
166 // I02 3
167 // I01 1/TX0
168
169 // start the AS8510 library:
170 AS8510 . begin ();
171 AS8510 . set_volt_calib ( 1167 ); //use to fine trim voltage measurement
172 AS8510 . set_curr_calib ( 1060 ); //use to fine trim current measurement
173
174 AS8510 . set_curr_gain ( 40 ); //possible gain values 1,5,25,40,100
175 AS8510 . autoconversion ();
176
177 // give the sensor time to set up:
178 delay ( 100 );
179
180 // INKREMENTALFGEBER
181 // Versorgungsspannung: +5 VDC ---> braun/grün
182 // GND ---> weiss/grün
183 //
184 //Geschwindigkeitsmessung
185 rpmcount = 0 ;
186 rpm = 0 ;
187 timeold = 0 ;
188
189 Timer1 . initialize ( 1000000 ); // Setze Timer auf 1sec
190 //Time1 aktivieren
191 //Timer1.attachInterrupt(timerISR);
192
193 //*********incinccounter inkrementieren oder dekrementieren -> ISR aktivieren
194 //INT1 - PIN3 / EMS INT
195 //----------------------
196 //INT0 - PIN2 / A
197 //INT5 - PIN18 / B
198 //INT4 - PIN19 / Z
199 //----------------------
200 //INT3 - PIN20 / DCF77
201 //INT2 - PIN21 / NN
202
203 //INT1 (Pin 3) wird von AMS genutzt!
204 //INT0 - PIN 2 (mega 2560) / A-Signal / braun
205 attachInterrupt ( 0 , S1_RISE , RISING );
206 //INT5 - PIN 18 (mega 2560) / B-Signal / grau
207 attachInterrupt ( 5 , S2_RISE , RISING );
208 //INT4 - PIN 19 (mega 2560) / Z-Signal / rot
209 attachInterrupt ( 4 , S3_RISE , RISING );
210 attachInterrupt ( 1 , AS8510 . ams (), RISING );
211
212 //eigene Chars
213 lcd . createChar ( 0 , batteryempty );
214 lcd . createChar ( 1 , battery25 );
215 lcd . createChar ( 2 , distancesymbol );
216 lcd . createChar ( 3 , arrowright );
217 }
218
219 void timerISR ()
220 {
221 Timer1 . detachInterrupt (); //stoppe den Timer
222 distance = distancem ;
223 speed = ( distance - distanceold );
224 //Serial.print("Geschwindigkeit: ");
225 //Serial.print(speed,3); Serial.print(",");
226 //Serial.print(distance,3); Serial.print(",");
227 //Serial.print(distanceold,3); Serial.print(",");
228
229 distanceold = distance ;
230 Timer1 . attachInterrupt ( timerISR ); //starte den Timer
231 }
232
233 void loop (){
234 //AMS Daten
235 voltagekorr = ( AS8510 . read_voltage () * 2 . 2403 ) - 12 . 518 ;
236 currentkorr = ( AS8510 . read_current () * 9 . 4487 ) - 0 . 0035 ;
237
238 //Umfang Messrad 500mm
239 //90 Grad Phasenverschiebung
240 //Inkremente
241 inc = incinccounter / 4 ;
242 //zurueckgelegter Weg
243 distancem = (( float ) inc / 1000 );
244
245 //INTEGER
246 distance_int = distancem * 1000 ;
247 speed_int = speed * 100 ;
248 humi_int = sht3x . getHumidity () * 100 ;
249 temp_int = sht3x . getTemperature () * 100 ;
250
251 //Restart the interrupt processing
252 //INT0 - pin2 (mega 2560) / A-Signal / braun
253 //attachInterrupt(4, S1_RISE, RISING);
254 //INT1 - pin 3 (mega 2560) / B-Signal / grau
255 //attachInterrupt(3, S2_RISE, RISING);
256 //INT2 - pin 21 (mega 2560) / Z-Signal / rot
257 //attachInterrupt(2, S3_RISE, RISING);
258
259 sht3x . readSample ();
260 //Führe eine Messung über 10 Impulse aus, ein Impuls dauert genau eine Sekunde
261 //q = DCF77signalQuality(10);
262
263 //if (millis() - previousMillis0 > interval) {
264 //previousMillis0 = millis(); // aktuelle Zeit abspeichern
265 // updateLCD(vin_old);
266 //}
267 if ( millis () - previousMillis1 > 1 ) {
268 previousMillis1 = millis (); // aktuelle Zeit abspeichern
269 serial ();
270 }
271 }
272
273
274 //****************************************************************************************************
275 // Quadratur Modulation
276 //
277
278 //Phase | Rotation im Uhrzeigersinn | Rotation gegen den Uhrzeigersinn
279 //- A B A B
280 //1 0 0 1 0
281 //2 0 1 1 1
282 //3 1 1 0 1
283 //4 1 0 0 0
284
285 void S1_RISE (){
286 detachInterrupt ( 0 );
287 S1_SIG = 1 ;
288
289 if ( S2_SIG == 0 )
290 incinccounter ++ ; //entry
291 if ( S2_SIG == 1 )
292 incinccounter -- ; //exit
293 //Serial.println(incinccounter);
294 attachInterrupt ( 0 , S1_FALL , FALLING );
295 }
296
297 void S1_FALL (){
298 detachInterrupt ( 0 );
299 S1_SIG = 0 ;
300
301 if ( S2_SIG == 1 )
302 incinccounter ++ ; //entry
303 if ( S2_SIG == 0 )
304 incinccounter -- ; //exit
305 //Serial.println(incinccounter);
306 attachInterrupt ( 0 , S1_RISE , RISING );
307 }
308
309 void S2_RISE (){
310 detachInterrupt ( 5 );
311 S2_SIG = 1 ;
312
313 if ( S1_SIG == 1 )
314 incinccounter ++ ;
315 if ( S1_SIG == 0 )
316 incinccounter -- ; //exit
317 //Serial.println(incinccounter);
318 attachInterrupt ( 5 , S2_FALL , FALLING );
319 }
320
321 void S2_FALL (){
322 detachInterrupt ( 5 );
323 S2_SIG = 0 ;
324
325 if ( S1_SIG == 0 )
326 incinccounter ++ ; //entry
327 if ( S1_SIG == 1 )
328 incinccounter -- ;
329 //inc=incinccounter/4;
330 //turns=(incinccounter/500);
331 //Serial.println(incinccounter);
332 attachInterrupt ( 5 , S2_RISE , RISING );
333 }
334
335 void S3_RISE (){
336 S3_SIG = 1 ;
337 detachInterrupt ( 4 );
338
339 if ( ! firstinit && (( S2_SIG == 1 && S1_SIG == 1 ) || ( S1_SIG == 0 && S2_SIG == 1 )))
340 {
341 incinccounter = 0 ;
342 firstinit = true ;
343 }
344 attachInterrupt ( 4 , S3_FALL , FALLING );
345 }
346
347 void S3_FALL (){
348 S3_SIG = 0 ;
349 detachInterrupt ( 4 );
350
351 if ( ! firstinit && (( S2_SIG == 1 && S1_SIG == 1 ) || ( S1_SIG == 1 && S2_SIG == 0 )))
352 {
353 incinccounter = 0 ;
354 firstinit = true ;
355 }
356 attachInterrupt ( 4 , S3_RISE , RISING );
357 }
358 // Ende der Quadratur Modulation
359 //****************************************************************************************************
360
361
362 void updateLCD ( float vin_old ){
363 lcd . clear ();
364 lcd . home (); // set cursor to 0,0
365 lcd . print ( "U_Bat: " );
366 lcd . print ( voltagekorr , 3 );
367 lcd . print ( " V " );
368 lcd . print ( "I_Bat: " );
369 lcd . print ( currentkorr , 3 );
370 lcd . print ( " A " );
371
372 //display battery state symbol
373 lcd . write (( uint8_t ) 1 );
374
375 //show distance
376 lcd . setCursor ( 0 , 1 ); // go to start of 2nd line
377 lcd . write (( uint8_t ) 2 );
378 lcd . print ( " " );
379 lcd . print ( inc );
380 lcd . print ( " mm " );
381
382 lcd . print ( distancem , 2 );
383 lcd . print ( " m " );
384
385 lcd . setCursor ( 0 , 2 ); // go to start of 2nd line
386 lcd . print ( "v= " );
387 lcd . print ( speed );
388 lcd . print ( " m/s " );
389
390 //Temp-LF
391 lcd . setCursor ( 0 , 3 ); // go to start of 3rd line
392 lcd . print ( sht3x . getHumidity (), 2 );
393 lcd . print ( " % " );
394 lcd . write (( uint8_t ) 3 );
395 lcd . print ( " " );
396 lcd . print ( sht3x . getTemperature (), 2 );
397
398 //Character Grad 11011111
399 lcd . print ( " " );
400 lcd . write ( 0 b11011111 );
401 lcd . print ( "C " );
402 }
403
404 void serial (){
405 //NUR INT AUSGEBEN!!!!
406 //Auswertung in Python
407 //distancem;speed;v_in;humidty;temperature
408 //Serial.print(distance,3); Serial.print(";");
409 Serial . print ( humi_int , DEC ); Serial . print ( ";" );
410 Serial . print ( temp_int , DEC ); Serial . print ( ";" );
411 //Serial.print(vin_int); Serial.print(";");
412 //Serial.print(current); Serial.print(";");
413 //Serial.print(distance_int); Serial.print(";");
414 Serial . print ( speed_int , DEC ); Serial . print ( ";" ); Serial . print ( " \n\r " );
415
416
417 Serial . print ( "INC= " );
418 Serial . print ( incinccounter );
419 Serial . print ( " \r \n " );
420 Serial . print ( "x[m]= " );
421 Serial . println ( distancem );
422 Serial . print ( " \r \n " );
423 //SHT3x
424 Serial . print ( "SHT3x: " );
425 Serial . print ( "RH: " );
426 Serial . print ( sht3x . getHumidity (), 2 );
427 Serial . print ( " % \r \n " );
428 Serial . print ( "T: " );
429 Serial . print ( sht3x . getTemperature (), 2 );
430 Serial . print ( " Grad Celsius \r \n " );
431
432 //Wenn kein Wechsel zwischen HIGH und LOW am Anschluss erkannt wurde
433 //bedeutet das in 99,99% aller Fälle das der DCF Empfänger nicht arbeitet
434 //denn bei extrem schlechten Empfang hat man Wechsel, nur kann man sie nicht auswerten.
435 //if (!q) {Serial.print("# (Schaltung pruefen!)");}
436
437 //for (int i = 0; i < q; i++) {
438 // Serial.print(">");
439 //}
440 //Serial.println("");
441 }
442
443 int DCF77signalQuality ( int pulses ) {
444 int prevSensorValue = 0 ;
445 unsigned long loopTime = 10000 ; //Impuls Länge genau eine Sekunde
446 //Da wir ja mitten in einem Impuls einsteigen könnten, verwerfen wir den ersten.
447 int rounds = - 1 ;
448 unsigned long gagingStart = 0 ;
449 unsigned long waitingPeriod = 0 ;
450 int overallChange = 0 ;
451 int change = 0 ;
452
453 while ( true ) {
454 //Unsere Schleife soll das Eingangssignal (LOW oder HIGH) 10 mal pro
455 //Sekunde messen um das sicherzustellen, messen wir dessen Ausführungszeit.
456 gagingStart = micros ();
457 int sensorValue = digitalRead ( DCF77PIN );
458 //Wenn von LOW nach HIGH gewechselt wird beginnt ein neuer Impuls
459 if ( sensorValue == 1 && prevSensorValue == 0 ) {
460 rounds ++ ;
461 if ( rounds > 0 && rounds < pulses + 1 ) { overallChange += change ;}
462 if ( rounds == pulses ) { return overallChange / pulses ;}
463 change = 0 ;
464 }
465 prevSensorValue = sensorValue ;
466 change ++ ;
467
468 //Ein Wechsel zwichen LOW und HIGH müsste genau alle 100 Durchläufe stattfinden
469 //wird er größer haben wir kein Empfang
470 //300 habe ich als guten Wert ermittelt, ein höherer Wert würde die Aussage festigen
471 //erhöht dann aber die Zeit.
472 if ( change > 300 ) { return 0 ;}
473 //Berechnen und anpassen der Ausführungszeit
474 waitingPeriod = loopTime - ( micros () - gagingStart );
475 delayMicroseconds ( waitingPeriod );
476 }
477 }
1 #ifndef _AS8510_H_INCLUDED
2 #define _AS8510_H_INCLUDED
3
4 #include <stdio.h>
5 #include <Arduino.h>
6 #include <avr/pgmspace.h>
7
8 #define DREG_I1 0x00
9 #define DREG_I2 0x01
10 #define DREG_V1 0x02
11 #define DREG_V2 0x03
12 #define STATUS_REG 0x04
13 #define DEC_REG_R1_I 0x05
14 #define DEC_REG_R2_I 0x06
15 #define FIR_CTL_REG_I 0x07
16 #define CLK_REG 0x08
17 #define RESET_REG 0x09
18 #define MOD_CTL_REG 0x0A
19 #define MOD_TA_REG1 0x0B
20 #define MOD_TA_REG2 0x0C
21 #define MOD_ITH_REG1 0x0D
22 #define MOD_ITH_REG2 0x0E
23 #define MOD_TMC_REG1 0x0F
24 #define MOD_TMC_REG2 0x10
25 #define NOM_ITH_REG1 0x11
26 #define NOM_ITH_REG2 0x12
27 #define PGA_CTL_REG 0x13
28 #define PD_CTL_REG_1 0x14
29 #define PD_CTL_REG_2 0x15
30 #define PD_CTL_REG_3 0x16
31 #define ACH_CTL_REG 0x17
32 #define ISC_CTL_REG 0x18
33 #define OTP_EN_REG 0x19
34 #define OTP_REG_0 0x25
35 #define OTP_REG_1 0x26
36 #define OTP_REG_2 0x27
37 #define STATUS_REG_2 0x44
38 #define DEC_REG_R1_V 0x45
39 #define DEC_REG_R2_V 0x46
40 #define FIR_CTL_REG_V 0x47
41
42 #define CURRENT_GAIN_5 0x00
43 #define CURRENT_GAIN_25 0x40
44 #define CURRENT_GAIN_40 0x80
45 #define CURRENT_GAIN_100 0xC0
46
47 #define BYPASS_VOLTAGE_PGA 0xF7
48 #define BYPASS_CURRENT_PGA 0xFB
49
50
51
52 #define SPI_CLOCK_DIV4 0x00
53 #define SPI_CLOCK_DIV16 0x01
54 #define SPI_CLOCK_DIV64 0x02
55 #define SPI_CLOCK_DIV128 0x03
56 #define SPI_CLOCK_DIV2 0x04
57 #define SPI_CLOCK_DIV8 0x05
58 #define SPI_CLOCK_DIV32 0x06
59
60 #define SPI_MODE0 0x00
61 #define SPI_MODE1 0x04
62 #define SPI_MODE2 0x08
63 #define SPI_MODE3 0x0C
64
65 #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
66 #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
67 #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
68
69 #define CS_PIN 10
70 #define INT_PIN 3
71
72 class AS8510Class {
73 public:
74 AS8510Class ();
75 static void begin (); // Default
76 void autoconversion ();
77 static void config ();
78 static void ams ();
79 static void set_curr_gain ( unsigned char gain );
80 void getvoltage2 ( float * v , float * i );
81 static void start ();
82 static void end ();
83 inline void set_curr_calib ( float calib );
84 inline void set_volt_calib ( float calib );
85 inline float read_voltage ();
86 inline float read_current ();
87 void spiwr ( unsigned char addr , unsigned char data );
88 unsigned char spird ( unsigned char addr );
89 void spird4 ( unsigned char addr , unsigned char * DataIn );
90
91 private:
92 float curr_calib , volt_calib ;
93
94 };
95
96 extern volatile float voltage , current ;
97 extern AS8510Class AS8510 ;
98
99 void AS8510Class :: set_volt_calib ( float calib )
100 {
101 volt_calib = calib ;
102 }
103
104 void AS8510Class :: set_curr_calib ( float calib )
105 {
106 curr_calib = calib ;
107 }
108
109 float AS8510Class :: read_voltage ()
110 {
111 return ( getvoltage2 / volt_calib );
112 }
113
114 float AS8510Class :: read_current ()
115 {
116 return ( current / curr_calib );
117 }
118
119 #endif
1 #include "pins_arduino.h"
2 #include "AS8510.h"
3
4 volatile float voltage , current ;
5 AS8510Class AS8510 ;
6
7 AS8510Class :: AS8510Class ()
8 {
9 current = 0 ;
10 voltage = 0 ;
11 curr_calib = 2635 ;
12 volt_calib = 1160 ;
13
14 }
15
16 void AS8510Class :: begin () {
17
18 // start the SPI library:
19 // Set SS to high so a connected chip will be "deselected" by default
20 digitalWrite ( SS , HIGH );
21
22 // When the SS pin is set as OUTPUT, it can be used as
23 // a general purpose output port (it doesn't influence
24 // SPI operations).
25 // initalize the data ready and chip select pins:
26 pinMode ( SS , OUTPUT );
27 pinMode ( INT_PIN , INPUT );
28 pinMode ( CS_PIN , OUTPUT );
29
30 // Warning: if the SS pin ever becomes a LOW INPUT then SPI
31 // automatically switches to Slave, so the data direction of
32 // the SS pin MUST be kept as OUTPUT.
33 SPCR |= _BV ( MSTR );
34 SPCR |= _BV ( SPE );
35
36 // Set direction register for SCK and MOSI pin.
37 // MISO pin automatically overrides to INPUT.
38 // By doing this AFTER enabling SPI, we avoid accidentally
39 // clocking in a single bit since the lines go directly
40 // from "input" to SPI control.
41 // http://code.google.com/p/arduino/issues/detail?id=888
42 #ifdef __AVR__
43 pinMode ( SCK , OUTPUT );
44 pinMode ( MOSI , OUTPUT );
45 #endif
46
47 SPCR = ( SPCR & ~ SPI_MODE_MASK ) | SPI_MODE3 ;
48 SPCR = ( SPCR & ~ SPI_CLOCK_MASK ) | ( SPI_CLOCK_DIV8 & SPI_CLOCK_MASK );
49 SPSR = ( SPSR & ~ SPI_2XCLOCK_MASK ) | (( SPI_CLOCK_DIV8 >> 2 ) & SPI_2XCLOCK_MASK );
50
51 AS8510 . config ();
52 }
53
54 void AS8510Class :: autoconversion ()
55 {
56 //EICRA |= (1 << ISC00)|(1 << ISC01); // set INT0 to trigger on rising edge
57 EICRA |= ( 1 << ISC10 ) | ( 1 << ISC11 ); // set INT1 to trigger on rising edge
58 //EIMSK |= (1 << INT0); // Turns on INT0
59 EICRA |= ( 1 << INT1 ); // Turns on INT1
60 AS8510 . start ();
61 }
62
63 void AS8510Class :: ams ()
64 {
65 unsigned char reg [ 4 ];
66 AS8510 . spird4 ( 0 , & reg [ 0 ]); //read the four bits of voltage 1 and 2
67
68 current = (( reg [ 0 ] << 8 ) | reg [ 1 ]);
69 voltage = (( reg [ 2 ] << 8 ) | reg [ 3 ]);
70 }
71
72
73 void AS8510Class :: config ()
74 {
75 AS8510 . spiwr ( RESET_REG , 0 ); //reset
76 delay ( 50 );
77
78 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_40 );
79 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
80
81 AS8510 . spiwr ( PD_CTL_REG_3 , 0xFC ); //output in 2's complement
82 AS8510 . spiwr ( ACH_CTL_REG , ETR );
83
84 #ifdef FAST_ACQ
85 AS8510 . spiwr ( DEC_REG_R1_I , 0x4B ); // CIC1-64, Chop-CLK=2K, CIC2-4, ( SDM clock = 1MHz )
86 AS8510 . spiwr ( DEC_REG_R1_V , 0x4B ); // CIC1-64, Chop-CLK=2K, CIC2-4, ( SDM clock = 1MHz )
87 #else
88 AS8510 . spiwr ( DEC_REG_R1_I , 0x4F ); // CIC1-64, Chop-CLK=2K, CIC2-128, ( SDM clock = 1MHz )
89 AS8510 . spiwr ( DEC_REG_R1_V , 0x4F ); // CIC1-64, Chop-CLK=2K, CIC2-128, ( SDM clock = 1MHz )
90 #endif
91 }
92
93 void AS8510Class :: set_curr_gain ( unsigned char gain )
94 {
95 switch ( gain )
96 {
97 case 1 :
98 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA | BYPASS_CURRENT_PGA );
99 break ;
100 case 5 :
101 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_5 );
102 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
103 break ;
104 case 25 :
105 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_25 );
106 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
107 break ;
108 case 40 :
109 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_40 );
110 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
111 break ;
112 case 100 :
113 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_100 );
114 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
115 break ;
116 default:
117 AS8510 . spiwr ( PGA_CTL_REG , CURRENT_GAIN_40 );
118 AS8510 . spiwr ( PD_CTL_REG_2 , BYPASS_VOLTAGE_PGA );
119 break ;
120 }
121 }
122
123 void AS8510Class :: getvoltage2 ( float * v , float * i )
124 {
125 unsigned char reg [ 4 ];
126 AS8510 . spird4 ( 0 , & reg [ 0 ]); //read the four bits of voltage 1 and 2
127
128 * i = (( reg [ 0 ] << 8 ) | reg [ 1 ]) / curr_calib ;
129 * v = (( reg [ 2 ] << 8 ) | reg [ 3 ]) / volt_calib ;
130 }
131
132
133 void AS8510Class :: start ()
134 {
135 AS8510 . spiwr ( 0x0A , AS8510 . spird ( 0x0A ) | 0x01 ); //set start bit
136 }
137
138 void AS8510Class :: end ()
139 {
140 AS8510 . spiwr ( 0x0A , AS8510 . spird ( 0x0A ) & 0xFE ); //clear start bit
141 }
142
143 // writing of one data byte at Adr0
144 void AS8510Class :: spiwr ( unsigned char addr , unsigned char data )
145 {
146 // take the chip select low to select the device:
147 digitalWrite ( CS_PIN , LOW );
148
149 SPDR = addr & 0x7F ; //Send register location
150 while ( ! ( SPSR & _BV ( SPIF )));
151 SPDR = data ; //Send value to record into register
152 while ( ! ( SPSR & _BV ( SPIF )));
153
154 // take the chip select high to de-select:
155 digitalWrite ( CS_PIN , HIGH );
156 }
157
158 // reading of one data byte from Adr0 into DataIn[0]
159 unsigned char AS8510Class :: spird ( unsigned char addr )
160 {
161 unsigned char dat ;
162 // take the chip select low to select the device:
163 digitalWrite ( CS_PIN , LOW );
164
165 SPDR = addr | 0x80 ; //Send register location and read
166 while ( ! ( SPSR & _BV ( SPIF )));
167 SPDR = 0xFF ;
168 while ( ! ( SPSR & _BV ( SPIF ))); //Read value
169 dat = SPDR ;
170
171 // take the chip select high to de-select:
172 digitalWrite ( CS_PIN , HIGH );
173
174 return dat ;
175 }
176
177 // reading of four data bytes beginning from Adr0 into DataIn[0..3]
178 void AS8510Class :: spird4 ( unsigned char addr , unsigned char * DataIn )
179 {
180 unsigned char i ;
181
182 // take the chip select low to select the device:
183 digitalWrite ( CS_PIN , LOW );
184
185 SPDR = addr | 0x80 ; //Send register location and read
186 while ( ! ( SPSR & _BV ( SPIF )));
187
188 for ( i = 0 ; i < 4 ; i ++ )
189 {
190 SPDR = 0xFF ;
191 while ( ! ( SPSR & _BV ( SPIF ))); //Read value
192 DataIn [ i ] = SPDR ;
193 }
194
195 // take the chip select high to de-select:
196 digitalWrite ( CS_PIN , HIGH );
197
198 }
08.02.2017 11:24 :
Bearbeitet durch User
von
Yalu X.
(yalu )
(Moderator )
08.02.2017 14:16
Eins vorweg: Poste solch lange Quellcodelistings besser als Anhang,
sonst sind die Leser fast nur mit dem Durchscrollen des Threads
beschäftigt.
1 attachInterrupt ( 1 , AS8510 . ams (), RISING );
Nach ams gehört kein Klammerpaar, da du einen Funktionszeiger und nicht
das Ergebnis eines Funktionsaufrufs übergeben willst. Da der Rückgabetyp
von AS8510.ams void, also "nichts" ist, meckert das der Compiler an,
allerdings nicht mit dieser Meldung:
> 'class AS8510Class' has no member named 'ams'
Diese Fehlermeldung passt nicht zu dem geposteten Quellcode, egal ob mit
oder ohne das Klammerpaar.
Es war tatsächlich ein falscher Verweis auf eine andere Bibliothek
gesetzt.
Ich habe das korrigiert und nun läuft es.
Vielen vielen Dank!!!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.