[Arduino] Globale variable

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Looney11
  • Registratie: December 2004
  • Laatst online: 09-10 21:27
Hallo allemaal,

Onlangs hebben we een projectje opgestart en hierbij een Arduino geprogrammeerd. In hardware zijn we sterk genoeg om ons mannetje te staan maar bij software short het nog wel eens..
In mijn beleving zijn variabelen die voor void setup en void loop worden gedeclareerd, voor iedere functie toegankelijk.

Echter, in ons programma moeten we in de functie switchoff alsnog de potvalue laten berekenen.
Het gaat dan met name om regel 81, als ik deze bovenin zet, wordt de variabele niet bewaard.
Als ik de variabele helemaal bovenin zet, dus buiten de context van de functie, geeft de functie de waarde 0 terug.
Als ik de variabele in de methode zet, wordt deze wel correct weergegeven.

Dit is in weze niet zo erg, het werkt zo, alleen vind ik het raar dat deze variabele niet globaal gezien wordt.

Mis ik soms iets?
Onderstaand de code, e.e.a. heb ik gekuisd :)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <LiquidCrystal.h> //make use of the HD44780 compatible LCD controller
LiquidCrystal lcd(12, 11, 10, 9, 5, 4); //initialize the used pins by the LCD

int optoH = 7; //Optocoupler High signal
int optoL = 6; //Optocoupler Low signal
int startbutton = 2; //Start of switchoff sequence
int resetbutton = 3; //Reset after start sequence is completed
int mosfetOut = 8; //Mosfet switch output from arduino, low = mosfet closed, high = mosfet open
int sbuttonState = 0; //State of startbutton
int rbuttonState = 0; //State of resetbutton
float duration, pulseHigh, pulseLow, fre; //variabeles declared to be floating

byte logo[8] = { //Logo of company
  B10100,
  B10000,
  B11010,
  B11010,
  B10011,
  B11111,
  B11111,
};


void setup()
{
  //Serial.begin(9600);
  pinMode(optoH, INPUT);
  pinMode(optoL, INPUT);
  pinMode(mosfetOut, OUTPUT);      
  pinMode(startbutton, INPUT);     
  pinMode(resetbutton, INPUT);
   // set up the LCD's number of columns and rows: 
  lcd.createChar(0,logo); //initializes logo on LCD
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("XXXXXXXXXX");
  lcd.setCursor(14,0);
  lcd.write(byte(0)); //writes logo to LCD screen
  lcd.setCursor(0, 1);
    lcd.print("AC peak detector");
    delay(2000);
    lcd.clear();
  
}

void loop()
{
  //Serial.println('duration');
  pulseHigh = pulseIn(optoH, HIGH);
  pulseLow = pulseIn(optoL,LOW);
  duration= pulseHigh+pulseLow;
  duration = duration / 1E6;
  fre=(1/duration);
  int potValue = analogRead(A0);
  lcd.setCursor(0,0);
  lcd.print(fre,1);
  lcd.print("Hz");
  lcd.setCursor(0,1);
  lcd.print(potValue * 5);
  lcd.print(" usec delay");
  //Serial.println(fre); //geeft de frequentie weer
  //Serial.println(potValue); //geeft de potmeter waarde weer
  
  
  // read the state of the pushbutton value:
  sbuttonState = digitalRead(startbutton);
  rbuttonState = digitalRead(resetbutton);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (sbuttonState == HIGH) {  // check state of start button, if high, go to switchoff   
    switchoff();// run switch off routine 
      } 
  else {
    if (rbuttonState == HIGH) { //check state of reset button, if high, go to reset
    reset();   //run reset routine
      } 
  }
}
void switchoff()
{ int potValue = analogRead(A0); 
  int timeout = (potValue * 5);
  //int optoH = 7;
      if (pulseIn(optoH,HIGH))
      {
      delayMicroseconds(timeout);
      digitalWrite(mosfetOut,LOW);
      }
}
void reset()
{    digitalWrite(mosfetOut,HIGH);
}

[ Voor 3% gewijzigd door Looney11 op 02-05-2013 17:17 . Reden: verwarrende zin aangepast. ]


Acties:
  • 0 Henk 'm!

  • ThinkCreative
  • Registratie: Oktober 2009
  • Laatst online: 09-10 12:47
Komt dit niet doordat de PIN waar de potmeter opzit nog niet op de juiste mode is gezet. Dit gebeurt immers pas in de setup.

Wat gebeurt er als je de variable potValue globaal initialiseerd (int potValue;) en dan berekent in de setup?


Edit: Zie nu dat de pinmode waarop de potmeter zit niet eens wordt gezet in de setup, omdat je hier toch een inputpin voor gebruikt 8)7 . Dus mijn suggestie zou eigenlijk niets moeten veranderen, lijkt me. Eigenaardig probleem.

[ Voor 33% gewijzigd door ThinkCreative op 02-05-2013 16:20 ]


Acties:
  • 0 Henk 'm!

  • Juicy
  • Registratie: December 2000
  • Laatst online: 11:21
In je voorbeeld bestaat je variabele alleen binnen de context van de methode. Verplaats je de variabele buiten de context van de methode, dus bij je andere variabelen bovenin je voorbeeld, dan wordt deze op een hoger nivo toegankelijk. Binnen je methode kun je deze dan zetten.
Looney11 schreef op donderdag 02 mei 2013 @ 16:00:
Als ik na regel 81, zonder dat in deze functie potvalue berekent wordt, maar wel bovenin, het programma de potvalue waarde laat teruglezen middels serial.println, geeft het programma steeds 0.
Ik begrijp totaal niet wat je hier probeert te vertellen ...

-


Acties:
  • 0 Henk 'm!

  • Looney11
  • Registratie: December 2004
  • Laatst online: 09-10 21:27
Ik geef toe, na het lezen van die zin dat ik er zelf ook geen tabak van maak. Wat ik wil zeggen is dit:

Als ik de variabele helemaal bovenin zet, dus buiten de context van de functie, geeft de functie de waarde 0 terug.
Als ik de variabele in de methode zet, wordt deze wel correct weergegeven.

Acties:
  • 0 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 13:18
Je moet globale variabelen die buiten de normale programmastructuur worden gebruikt (bijvoorbeeld door interrupts) voorzien van het volatile keyword. Anders krijg je ruzie met de optimiser.
Wikipedia: Volatile variable

Of je declareert de variabelen in de scope van de functie, maar in globaal geheugengebied (dus niet op stack) met het static keyword.
Wikipedia: Static variable

[ Voor 35% gewijzigd door jeroen3 op 02-05-2013 17:25 ]


Acties:
  • 0 Henk 'm!

  • Looney11
  • Registratie: December 2004
  • Laatst online: 09-10 21:27
Bedankt voor je antwoord, maar daar gaat het nu precies fout. Als we potvalue als globale variabele declareren, geeft ie steeds 0 terug. Als we 'm in de functie zetten, gaat het wel goed.

Dat is raar, want het is niet in lijn met wat Arduino zelf zegt over het declareren van variabelen:
Variable Scope

Variables in the C programming language, which Arduino uses, have a property called scope. This is in contrast to languages such as BASIC where every variable is a global variable.
A global variable is one that can be seen by every function in a program. Local variables are only visible to the function in which they are declared. In the Arduino environment, any variable declared outside of a function (e.g. setup(), loop(), etc. ), is a global variable.
When programs start to get larger and more complex, local variables are a useful way to insure that only one function has access to its own variables. This prevents programming errors when one function inadvertently modifies variables used by another function.
It is also sometimes handy to declare and initialize a variable inside a for loop. This creates a variable that can only be accessed from inside the for-loop brackets.
Example:
int gPWMval; // any function will see this variable

void setup()
{
// ...
}

void loop()
{
int i; // "i" is only "visible" inside of "loop"
float f; // "f" is only "visible" inside of "loop"
// ...

for (int j = 0; j <100; j++){
// variable j can only be accessed inside the for-loop brackets
}

}

Acties:
  • 0 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 13:18
Maak hem toch maar volatile. Of zet de optimiser uit. ( -O0 )
Een AnalogRead kan hij namelijk niet voorspellen.

Edit:
code:
1
2
int potValue = analogRead(A0); 
int timeout = (potValue * 5);

zal waarschijnlijk dit worden
code:
1
delayMicroseconds( 5 * analogRead(A0) )

De variabelen potValue en timeout bestaan dus alleen in registers.

Bekijk de disassembler eens. (.lss)
Als arduino die maakt?

[ Voor 88% gewijzigd door jeroen3 op 02-05-2013 18:00 ]


Acties:
  • 0 Henk 'm!

  • Infant
  • Registratie: Januari 2008
  • Laatst online: 11:30

Infant

It's a floating Dino!

Volgens mij hoeft volatile eigenlijk alleen als hij vanuit een interrupt gemodificeerd kan worden.

Als je de variabele buiten de functie maakt, haal je de declaratie dan wel uit de functies weg?

Dus:

C:
1
2
3
4
5
int i=0;

void main(){
    i=foo(bar);
}


En niet zo:

C:
1
2
3
4
5
int i=0;

void main(){
    int i=foo(bar);
}

Acties:
  • 0 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 13:18
Met het Volatile keyword forceer je de compiler de variabele te benaderen met de Read-Modify-Write methode. Ofwel, lezen uit sram, bewerking, schrijven naar sram. Zo kan er nooit sprake zijn van weg-geoptimaliseerde globals. Dat is inderdaad minder efficiënt.

Je definieert de variabele trouwens twee keer.
In switchoff() en in loop().
In die laatste zelfs halverwege de functie, en dat mag helemaal niet. definities doe je bovenaan een block { .. }

[ Voor 5% gewijzigd door jeroen3 op 03-05-2013 23:39 ]


Acties:
  • 0 Henk 'm!

  • bobo1on1
  • Registratie: Juli 2001
  • Laatst online: 18-05 17:57
Arduino gebruikt C++, daar mogen declaraties intermingled worden met code, en vanaf C99 mag dat ook.

Impedance, a measure of opposition to time-varying electric current in an electric circuit.
Not to be confused with impotence.


Acties:
  • 0 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 13:18
Dat C++ had ik kunnen weten natuurlijk.
Neem niet weg dat het niet netjes is om te 'interminglen".

[ Voor 10% gewijzigd door jeroen3 op 04-05-2013 10:56 ]


Acties:
  • 0 Henk 'm!

  • Looney11
  • Registratie: December 2004
  • Laatst online: 09-10 21:27
Het probleem blijft bestaan als ik potvalue declareer voordat de routines beginnen, heeft dit dan te maken met een analogRead?

Het volatile verklaren van de variable werkt niet, blijft 0 teruggeven.

Acties:
  • 0 Henk 'm!

  • bobo1on1
  • Registratie: Juli 2001
  • Laatst online: 18-05 17:57
Dan zal je toch eens je code moeten posten, anders kunnen we nooit het probleem aanwijzen.

Impedance, a measure of opposition to time-varying electric current in an electric circuit.
Not to be confused with impotence.


Acties:
  • 0 Henk 'm!

  • Looney11
  • Registratie: December 2004
  • Laatst online: 09-10 21:27
Mijn code staat in de eerste post. Daar word nu de variabele potvalue per functie aangeroepen omdat, als ik deze globaal declareer, niet wordt gebruikt door de functies.

Acties:
  • 0 Henk 'm!

  • bobo1on1
  • Registratie: Juli 2001
  • Laatst online: 18-05 17:57
En post nou eens de niet werkende code :)

Impedance, a measure of opposition to time-varying electric current in an electric circuit.
Not to be confused with impotence.


Acties:
  • 0 Henk 'm!

  • Flake
  • Registratie: Februari 2001
  • Laatst online: 01-11-2024
Ik zou ook niet weten waarom dat niet zou werken. Post es hoe jij je code wil zien ipv de code die je nu hebt. Misschien is het zo'n stom foutje (int laten staan ofzo) waardoor het niet werkt.

Wat ik nu zie is dat je potvalue zowel in je loop als in die functie uitleest, en die loop komt altijd voorbij, ongeacht wat switchoff doet. Daarnaast heb je volgens mij een bracket teveel aan het einde van je loop? Weet je zeker dat je goeie conclusies trekt?

Acties:
  • 0 Henk 'm!

  • Looney11
  • Registratie: December 2004
  • Laatst online: 09-10 21:27
Hierbij de code die niet werkt

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <LiquidCrystal.h> //make use of the HD44780 compatible LCD controller
LiquidCrystal lcd(12, 11, 10, 9, 5, 4); //initialize the used pins by the LCD

int optoH = 7; //Optocoupler High signal
int optoL = 6; //Optocoupler Low signal
int startbutton = 2; //Start of switchoff sequence
int resetbutton = 3; //Reset after start sequence is completed
int mosfetOut = 8; //Mosfet switch output from arduino, low = mosfet closed, high = mosfet open
int sbuttonState = 0; //State of startbutton
int rbuttonState = 0; //State of resetbutton
int potvalue = analogRead(A0);
float duration, pulseHigh, pulseLow, fre; //variabeles declared to be floating

byte logo[8] = { //Logo of company
  B10100,
  B10000,
  B11010,
  B11010,
  B10011,
  B11111,
  B11111,
};


void setup()
{
  //Serial.begin(9600);
  pinMode(optoH, INPUT);
  pinMode(optoL, INPUT);
  pinMode(mosfetOut, OUTPUT);      
  pinMode(startbutton, INPUT);     
  pinMode(resetbutton, INPUT);
   // set up the LCD's number of columns and rows: 
  lcd.createChar(0,logo); //initializes logo on LCD
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("XXXXXXXXXX");
  lcd.setCursor(14,0);
  lcd.write(byte(0)); //writes logo to LCD screen
  lcd.setCursor(0, 1);
    lcd.print("AC peak detector");
    delay(2000);
    lcd.clear();
  
}

void loop()
{
  //Serial.println('duration');
  pulseHigh = pulseIn(optoH, HIGH);
  pulseLow = pulseIn(optoL,LOW);
  duration= pulseHigh+pulseLow;
  duration = duration / 1E6;
  fre=(1/duration);
  // int potValue = analogRead(A0);
  lcd.setCursor(0,0);
  lcd.print(fre,1);
  lcd.print("Hz");
  lcd.setCursor(0,1);
  lcd.print(potValue * 5);
  lcd.print(" usec delay");
  //Serial.println(fre); //geeft de frequentie weer
  //Serial.println(potValue); //geeft de potmeter waarde weer
  
  
  // read the state of the pushbutton value:
  sbuttonState = digitalRead(startbutton);
  rbuttonState = digitalRead(resetbutton);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (sbuttonState == HIGH) {  // check state of start button, if high, go to switchoff   
    switchoff();// run switch off routine 
      } 
  else {
    if (rbuttonState == HIGH) { //check state of reset button, if high, go to reset
    reset();   //run reset routine
      } 
  }
}
void switchoff()
{ //int potValue = analogRead(A0); 
  int timeout = (potValue * 5);
  //int optoH = 7;
      if (pulseIn(optoH,HIGH))
      {
      delayMicroseconds(timeout);
      digitalWrite(mosfetOut,LOW);
      }
}
void reset()
{    digitalWrite(mosfetOut,HIGH);
}

Acties:
  • 0 Henk 'm!

  • Armageddon_2k
  • Registratie: September 2002
  • Laatst online: 07-10 14:00

Armageddon_2k

Trotse eigenaar: Yamaha R6

Probleem gevonden denk ik zo.

De functie: analogRead(A0) lees de analoge waarde op het moment dat je die functie uitvoert.
Jij voer nu de read nooit meer uit.

Oplossing overal waar jij:
code:
1
 // int potValue = analogRead(A0);

Moet gewoon worden:
code:
1
 potValue = analogRead(A0);

[ Voor 42% gewijzigd door Armageddon_2k op 16-05-2013 15:00 ]


Acties:
  • 0 Henk 'm!

  • Flake
  • Registratie: Februari 2001
  • Laatst online: 01-11-2024
^^ wat hij zegt. Daarnaast set je die global var tijdens declaratie, dat zou ik met analogRead niet doen omdat je pinmodes nog unknown zijn.

Acties:
  • 0 Henk 'm!

  • Looney11
  • Registratie: December 2004
  • Laatst online: 09-10 21:27
Ah ok, helder, ik pas het aan.

Bedankt voor de hulp!
Pagina: 1