Forum: Mikrocontroller und Digitale Elektronik Arduino C++ funktioniert nicht


von Anonymous U. (gastt)


Lesenswert?

Ich will ein kleines Programm mit der Arduino IDE schreiben. Nun habe 
ich das Problem, dass Folgende Fehlermeldung kommt:
exit status 1
no match for 'operator=' (operand types are 'volatile s_cinematic' and 
'volatile s_cinematic')

In AVR Studio funktioniert alles einwandfrei. Warum macht Arduino (gcc) 
solche Zickereien? C ist doch eine Untermenge von C++, warum 
funktioniert das nicht?

Mein Programm (Fehlerzeile durch ### hervorgehoben):
1
/*  Calculation of acceleration in koordinates (6 degrees of freedom)
2
 *  10.12.15
3
 *  
4
 *  used prefixes:
5
 *  s_ struct definitions
6
 *  g_ global variables
7
 *  d_ preprocessor definitions
8
*/
9
10
//includes
11
  #include <stdio.h>
12
  #include <avr/io.h>
13
  #include <avr/interrupt.h>
14
//definitions
15
  #define d_filterlength 10
16
//custom datatypes
17
  struct s_cinematic{
18
    int16_t translation_x1;
19
    int16_t translation_x2;
20
    int16_t translation_x3;
21
    int16_t rotation_x1;
22
    int16_t rotation_x2;
23
    int16_t rotation_x3;
24
  };
25
//global variables
26
  //contains calculated values of position
27
  struct s_cinematic g_position;
28
  //contains calculated values of velocity
29
  struct s_cinematic g_velocity;
30
  //contains acceleration values, read from gyrosensor
31
  volatile struct s_cinematic g_acceleration[d_filterlength];
32
  volatile int8_t g_acceleration_pointer;
33
//function prototypes
34
  void readgyro();
35
  struct s_cinematic kalman();
36
  void integrate_cinematic(struct s_cinematic input,struct s_cinematic  *output, int8_t mul_translation, int8_t mul_rotation);
37
  
38
void setup() {
39
  ///configure Timer2 (8-bit) system clock
40
    //TOV on OC2A >> WGM22 WGM21 WGM20
41
    TCCR2A = (1<<WGM20)|(1<<WGM21);
42
    //system tick = 100u >> 2000clk/8=250 >> CS21
43
    TCCR2B = (1<<WGM22)|(1<<CS21);
44
    OCR2A = 249;
45
    //TOV enable
46
    TIMSK2 = (1<<TOIE2);
47
    sei();
48
}
49
50
//interrupt 100us
51
ISR(TIMER2_OVF_vect){
52
  //read new values
53
    readgyro();
54
  //filter values
55
    struct s_cinematic temp;
56
    temp = kalman();
57
  //integrate acceleration >> velocity
58
    integrate_cinematic(temp, &g_velocity, 1, 1);
59
  //integrate velocity >> position
60
    integrate_cinematic(g_velocity, &g_position, 1, 1);
61
  return;
62
}
63
64
void loop() {
65
  
66
}
67
68
//functions
69
void readgyro(){
70
  //read from gyro
71
    struct s_cinematic temp;
72
    //...
73
  //overtake new values
74
    ++g_acceleration_pointer;
75
    if(g_acceleration_pointer>=d_filterlength)
76
      g_acceleration_pointer=0;
77
    g_acceleration[g_acceleration_pointer] = (volatile struct s_cinematic)temp; //############
78
  return;
79
}
80
struct s_cinematic kalman(){
81
  struct s_cinematic temp;
82
  //...
83
  return temp;
84
}
85
void integrate_cinematic(struct s_cinematic input, struct s_cinematic  *output, int8_t mul_translation, int8_t mul_rotation){
86
  output->translation_x1 += input.translation_x1;
87
  output->translation_x2 += input.translation_x2;
88
  output->translation_x3 += input.translation_x3;
89
  output->rotation_x1 += input.rotation_x1;
90
  output->rotation_x2 += input.rotation_x2;
91
  output->rotation_x3 += input.rotation_x3;
92
  return;
93
}

von Karl H. (kbuchegg)


Lesenswert?

Anonymous U. schrieb:

>     g_acceleration[g_acceleration_pointer] = (volatile struct
> s_cinematic)temp; //############

wenn du mir jetzt noch erklärst, wozu du da ein volatile hineincastest

> C ist doch eine Untermenge von C++, warum funktioniert das nicht?

Nö.
Das bedeutet noch lange nicht, das alle Regeln von C und C++ in dieser 
Schnittmenge identisch sind. Das C Subset von C++ hat sich über die 
Jahre immer weiter von echtem C entfernt.

von Rene H. (Gast)


Lesenswert?

Das was Du machst ist kein C++, sondern einen falschen C Cast mit dem 
C++ Compiler kompiliert.

Halte Dich an C++ und Du hast keinen Kummer.

von Anonymous U. (gastt)


Lesenswert?

Ohne den cast funktionierts auch nicht. Warum ist der eigentlich falsch? 
Der Unterschied besteht doch nur im volatile.

Wie würde man sowas dann lösen?

von Karl H. (kbuchegg)


Lesenswert?

Ich bin ehrlich gesagt geneigt dir in der Sache recht zu geben. Das 
dürfte tatsächlich ein Compiler Fehler sein. Der sucht nach einer 
Operation, mit der er an eine volatile struct eine Zuweisung machen 
kann. Die gibt es allerdings nicht. Man könnte
* einen entsprechenden Operator schreiben
* das volatile auf der linken Seite wegcasten (schlechte Lösung)
* das Array überhaupt nicht volatile machen. Denn zum einen hat der 
Compiler sowieso keine Chance, Zugriffe wegzucachen und zum anderen wird 
es nur in der ISR benutzt.



Allerdings ist auch das
1
//interrupt 100us
2
ISR(TIMER2_OVF_vect){
3
  //read new values
sehr optimistisch, wenn der Kommentar stimmt.
Alle Gyros auslesen und einen Kalmanfilter drüber jagen und das alles in 
100us auf einem AVR? Da würde ich sagen: bis zum Beweis des Gegenteils 
glaube ich das erst mal nicht, dass sich das mit der zeit ausgeht.

von Rene H. (Gast)


Lesenswert?


von Anonymous U. (gastt)


Lesenswert?

> * einen entsprechenden Operator schreiben
Ehrlichgesagt will ich bei C bleiben, da kenn ich mich zumindest 
halbwegs aus.

> * das volatile auf der linken Seite wegcasten (schlechte Lösung)
Warum macht volatile bei einer Zuweisung überhaupt einen Unterschied? 
Ich dachte das dies nur ein Hinweis für den Compiler ist, damit er die 
Variable immer "zugänglich" hält, falls eine Interruptroutine 
unvorhergesehen darauf zugreift.

> * das Array überhaupt nicht volatile machen. Denn zum einen hat der
> Compiler sowieso keine Chance, Zugriffe wegzucachen und zum anderen wird
> es nur in der ISR benutzt.
Das wäre eine Idee, allerdings will ich mir nicht die Möglichkeit 
verbauen später aus der Hauptschleife darauf zugreifen zu können.

> Allerdings ist auch das//interrupt 100us
> ISR(TIMER2_OVF_vect){
>   //read new values
> sehr optimistisch, wenn der Kommentar stimmt.
> Alle Gyros auslesen und einen Kalmanfilter drüber jagen und das alles in
> 100us auf einem AVR? Da würde ich sagen: bis zum Beweis des Gegenteils
> glaube ich das erst mal nicht, dass sich das mit der zeit ausgeht.
Eine spezielle Anwendung habe ich für das Projekt nicht. Ist erstmal 
eher Spielerei. Den Timer werd ich zum Schluss dann so einstellen das 
der atmega auch genügend Zeit hat.

von Anonymous U. (gastt)


Lesenswert?

By the way: Ist das überhaupt ein gutes Gerüst, man liest ja öfters, 
dass globale Variablen "böse" sind. Mir fällt da allerdings keine 
einfachere bzw. übersichtlichere Möglichkeit ein.

von Mark B. (markbrandis)


Lesenswert?

Anonymous U. schrieb:
> By the way: Ist das überhaupt ein gutes Gerüst, man liest ja öfters,
> dass globale Variablen "böse" sind. Mir fällt da allerdings keine
> einfachere bzw. übersichtlichere Möglichkeit ein.

Was soll es sein, prozedurale Progammierung? OOP?

Bei Anwendung von OOP hat man üblicherweise Objekte, die zur Laufzeit 
untereinander Nachrichten austauschen.

In reinem C kann man mit lokalen bzw. modul-globalen Variablen arbeiten. 
Wer einen entsprechenden Wert braucht, der ruft eine Funktion auf die 
einem genau diesen Wert zurückgibt.

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.