Forum: Mikrocontroller und Digitale Elektronik multiple definition of 'vector_6'


von Manu S. (unamx)


Lesenswert?

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
  0b01110,
85
  0b11011,
86
  0b10001,
87
  0b10001,
88
  0b10001,
89
  0b10001,
90
  0b10001,
91
  0b11111
92
};
93
byte battery25[8] = {
94
  0b01110,
95
  0b11011,
96
  0b10001,
97
  0b10001,
98
  0b10001,
99
  0b11111,
100
  0b11111,
101
  0b11111
102
};
103
byte battery100[8] = {
104
  0b01110,
105
  0b11111,
106
  0b11111,
107
  0b11111,
108
  0b11111,
109
  0b11111,
110
  0b11111,
111
  0b11111
112
};
113
byte distancesymbol[8] = {
114
  0b00000,
115
  0b00000,
116
  0b10001,
117
  0b11111,
118
  0b10001,
119
  0b00000,
120
  0b00000,
121
  0b00000
122
};
123
byte arrowright[8] = {
124
  0b00000,
125
  0b01000,
126
  0b01100,
127
  0b01110,
128
  0b01111,
129
  0b01110,
130
  0b01100,
131
  0b01000
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(0b11011111);
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.

von Jim M. (turboj)


Lesenswert?

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.

von Manu S. (unamx)


Angehängte Dateien:

Lesenswert?

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) Benutzerseite


Lesenswert?

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?

von Manu S. (unamx)


Angehängte Dateien:

Lesenswert?

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)


Lesenswert?

Beim Arduino sind alle externen Interrupts durch die Laufzeitumgebung
bereits belegt. Deswegen kannst du einen Interrupthandler nicht mit

1
ISR(INTx_vect) { ... }

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.

von Manu S. (unamx)


Lesenswert?

@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
  0b01110,
86
  0b11011,
87
  0b10001,
88
  0b10001,
89
  0b10001,
90
  0b10001,
91
  0b10001,
92
  0b11111
93
};
94
byte battery25[8] = {
95
  0b01110,
96
  0b11011,
97
  0b10001,
98
  0b10001,
99
  0b10001,
100
  0b11111,
101
  0b11111,
102
  0b11111
103
};
104
byte battery100[8] = {
105
  0b01110,
106
  0b11111,
107
  0b11111,
108
  0b11111,
109
  0b11111,
110
  0b11111,
111
  0b11111,
112
  0b11111
113
};
114
byte distancesymbol[8] = {
115
  0b00000,
116
  0b00000,
117
  0b10001,
118
  0b11111,
119
  0b10001,
120
  0b00000,
121
  0b00000,
122
  0b00000
123
};
124
byte arrowright[8] = {
125
  0b00000,
126
  0b01000,
127
  0b01100,
128
  0b01110,
129
  0b01111,
130
  0b01110,
131
  0b01100,
132
  0b01000
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\365v S\365d");
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(0b11011111);
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
}

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Manu S. (unamx)


Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.