desktop

Modificar Valor de Variable de programa principal desde una Clase en Arduino

Estoy realizando un programa en el que requiero modificar el valor de una variable del programa principal desde una Clase y no logro encontrar el algoritmo correcto..

aqui el codigo en cuestion:

C++:
*******Archivo prueba.ino****

#include "iButton.h"

unsigned int State_in=0b10110; //definicion y Asignacion de Valor a Variable State_in

iButton myObj(&State_in); //construccion de objeto pasando como parametro la direccion de la variable State_in para el apuntador

void loop() {
 Serial.println(State_in,BIN); //Imprime Valor esperando primer valor igual a 10110 y segundo valor modificado desde clase igual a 10111
 Delay(1500);
 myObj.setState(true);
}

*******Archivo iButton.h****

class iButton {
  private:
    unsigned int Var; //Definicion de vairable Var privada
 
 public:
    iButton(unsigned int *var); //definicion de funcion de objeto
    bool setState(bool data);  //definicion de funcion de modificacion de bit
};

*******Archivo iButton.cpp****

#include "iButton.h" //inclucion de archivo .h

iButton::iButton(unsigned int *var) {  //funcion del objeto  con parametro el apuntaor de la variable
  Var = *var; //asignar el valor a Var del valor del apuntador
}

bool iButton::setState(bool data) {
  bitWrite(Var,0, data); // modificar la el valor de la Variable Var que es igual a 10110 por 10111
 
   // aqui deberia ir el algoritmo que desconozco para pasar de la variable Var a la variable State_in del sketch prueba.ino
 
}

Lo que desconozco es como acceder al apuntador de la variable State_in y asignarle el Valor de la variable Var.

de antemano gracias por sus colaboraciones.
 
¿Por qué necesitás el puntero? ¿No podés simplemente asignar la variable?:

C++:
class iButton {
  private:
    unsigned int Var; //Definicion de vairable Var privada
 
 public:
    iButton(unsigned int var); //definicion de funcion de objeto
    bool setState(bool data);  //definicion de funcion de modificacion de bit
};

C++:
iButton::iButton(unsigned int var) {  //funcion del objeto  con parametro el apuntaor de la variable
  Var = var; //asignar el valor a Var del valor del apuntador
}
 
El puntero sería según yo para regresarlo a la variable de del programa principal ... no se como sería pero algo como :
Código:
bool iButton::setState(bool data) {
  bitWrite(Var,0, data); // modificar la el valor de la Variable Var que es igual a 10110 por 10111
 
   *State_in=&Var; //Esto es lo que no se como regresar Var al la variable State_in
   //obvio que esto no funciona
 
}
 
Última edición por un moderador:
Ya entendí, sería algo así:

C++:
class iButton {
  private:
    unsigned int *Var;
 
 public:
    iButton(unsigned int *var); //definicion de funcion de objeto
    bool setState(bool data);  //definicion de funcion de modificacion de bit
};

*******Archivo iButton.cpp****

#include "iButton.h" //inclucion de archivo .h

iButton::iButton(unsigned int *var) {  //funcion del objeto  con parametro el apuntaor de la variable
  Var = var; //asignar el valor a Var del valor del apuntador
}

bool iButton::setState(bool data) {
  bitWrite(*Var,0, data); // modificar la el valor de la Variable Var que es igual a 10110 por 10111
  ...
  *Var = Nuevo_Valor;
}

De todas formas, pensá que estás usando una variable global, por tal motivo esto deja de tener sentido. Si valdría la pena si State_in la definís dentro del main.
 
No entiendo nada!
Para que tanto lío en cambiar el valor de una variable GLOBAL que es accedida por todo el planeta sin ninguna restricción????

Y eso que dice "definición de función de objeto" no sé de que se trata. En todo el universo se lo conoce como "constructor (de la instancia....ponele)" y de eso se trata.

PD: es una MUY mala idea usar variables globales....pero MUY con M de MUCHO!!!
 
Naaa... minucias futesas de los entornos de desarrollo modernos.
Para los que programamos en su día con el BASIC del Z80 y lenguajes similares, todas las variables eran globales.
Como estábamos acostumbrados a trabajar así, sufrimos mucho lidiando con los ámbitos de las variables en los entornos de desarrollo posteriores.
 
Última edición:
Para entornos de microcontroladores, donde tu proyecto muchas veces no pasan de 100 líneas de código, no pasa nada.

Yo soy de la idea de evitarlas en lo posible, pero hay situaciones como por ejemplo el manejo de interrupciones, que utilizar un buffer global ayuda y mucho.

De todas formas, como mencioné arriba, el uso de punteros para modificar una variable global, no tiene mucho sentido.
 
Estoy de acuerdo contigo en todo.

En aquel BASIC, el máximo número de líneas eran 9999. Por lo tanto, no podían ser proyectos muy extensos.
Aparte de eso:
No podía manejar interrupciones (no en BASIC).
No tenía operadores lógicos (AND, OR), ni de manejo de bits.
No existía el operador Módulo (resto de una división).
No existían los punteros, ni las clases, ni los objetos, ni las instancias, ni los constructores, ni los destructores.
Sólo saltos absolutos (GOTO) y llamadas a subrutinas (GOSUB).
Las variables se definían con LET y no tenían ámbito. Sólo había dos tipos: numéricas y de cadena.
En cambio, se podían definir funciones con un token específico (DEF FN) y llamarlas con otro token específico (FN).
 
Si me queda claro que no se entiende el problema todavia:
una manera de poder modificar una variable de un sketch desde una clase se hace de esta manera con la función extern...

Código:
****prueba .ino

#include "iButton.h"

unsigned int State_in = 0b10110; //definicion y Asignacion de Valor a Variable State_in

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(State_in, BIN); //Imprime Valor esperando primer valor igual a 10110 y segundo valor modificado desde clase igual a 10111
  delay(500);
  myObj.setState(0,true);
}
Código:
... ibutton.cpp

#include "iButton.h" //inclucion de archivo .h

extern Unsigned int State_in;  ///FIJARSE AQUI COMO SE  DECLARA PARA QUE SEA EXTERNA

void iButton::setState(int posvar,bool data) {
  bitWrite(State_in, posvar, data); // modificar la el valor de la Variable Var que es igual a 10110 por 10111
}
Código:
#ifndef iButton_h
#define iButton_h

#include <Arduino.h>

class iButton {
 public:
    void setState(int posvar,bool data);  //definicion de funcion de modificacion de bit
};
#endif

Es claro y obvio que solo estoy poniendo el código que se requiere para resolver el problema, el codigo completo son unos cuantos cientos de lineas mas, pero si las pongo tendrían mucho menos idea de lo que consulto.

Por lo que necesito así es porque quiero crear varios objetos mas o menos asi:

Código:
*******Archivo prueba.ino****

#include "iButton.h"

unsigned int State_in; //definicion y Asignacion de Valor a Variable State_in
unsigned int State_out;
unsigned int State_flag;

iButton myObj_a(&State_in); //construccion de objeto pasando como parametro la direccion de la variable State_in para el apuntador
iButton myObj_b(&State_in); //construccion de objeto pasando como parametro la direccion de la variable State_in para el apuntador

iButton myObj_1(&State_out);
iButton myObj_2(&State_out);
iButton myObj_3(&State_out);

iButton myObj_x(&State_flag);

void loop() {

*****ATENTOS AQUI: (estoy imprimiendo el Valor de las variables MODIFICADAS DESDE LA CLASE)

 Serial.println(State_in,BIN);
 Serial.println(State_out,BIN); //Imprime Valor esperando primer valor igual a 10110 y segundo valor modificado desde clase igual a 10111
 Serial.println(State_flag,BIN); //Imprime Valor esperando primer valor igual a 10110 y segundo valor modificado desde clase igual a 10111

 

Delay(1500);
****AQUI llamo la instancia o funcion o como le quieran llamar donde se deberia modifcar la variable State_in que es lo que no se o estoy consultando
 myObj_a.setState(1,true);
 myObj_a.setState(2,false);
 
}

*******Archivo iButton.h****

class iButton {
  private:
    unsigned int Var; //Definicion de vairable Var privada
 
 public:
    iButton(unsigned int *var); //definicion de funcion de objeto
    bool setState(int pos,bool data);  //definicion de funcion de modificacion de bit
};

*******Archivo iButton.cpp****

#include "iButton.h" //inclucion de archivo .h

iButton::iButton(unsigned int *var) {  //funcion del objeto  con parametro el apuntaor de la variable
  Var = *var; //asignar el valor a Var del valor del apuntador
}

bool iButton::setState(int pos,bool data) {
  bitWrite(Var,pos, data); // modificar la el valor de la Variable Var que es igual a 10110 por 10111
 
  */Aqui poder asignar el valor de la variable Var a al variableque se pasa como parametro
  */ya sea State_in, State_out o State_flag o la que el nombre se antoje poner.
  el problema de usar la funcion extern es que solo se le puede dar un nombre unico
 
}


Ya entendí, sería algo así:

C++:
class iButton {
  private:
    unsigned int *Var;
 
 public:
    iButton(unsigned int *var); //definicion de funcion de objeto
    bool setState(bool data);  //definicion de funcion de modificacion de bit
};

*******Archivo iButton.cpp****

#include "iButton.h" //inclucion de archivo .h

iButton::iButton(unsigned int *var) {  //funcion del objeto  con parametro el apuntaor de la variable
  Var = var; //asignar el valor a Var del valor del apuntador
}

bool iButton::setState(bool data) {
  bitWrite(*Var,0, data); // modificar la el valor de la Variable Var que es igual a 10110 por 10111
  ...
  *Var = Nuevo_Valor //esto nodeberia ser asi
    State_in=Var;    ////es lo que requiero pero no funciona porque no esta declara como externa
 //lo que requeiro es modificar la variable State_in del programa principal
[QUOTE="cosmefulanito04, post: 1484943, member: 62109"]
}
Casi se entiende, pero no es como dices cosmefulanito...

No creo que sea un problema sencillo pues he visto muchas consultas sobre eso y todos terminan diciendo que se utilice la función extern, pero como mencioné solo se puede utilizar variables externas con un nombre especifico.

Por lo del tema de BASIC, ya da flojera explicar que son herramientas distintas y con diferentes propositos..

Tiene que ser algo como esto pero aun no logro ver como ( aclaro que no entiendo del todo como funcionan los apuntadores entre el programa y las clases y tambien es obvio que si dominara los apuntadores no estaría consultando)
Código:
---prueba.ino---
#include "iButton.h"

unsigned int State_in = 0b10110; //definicion y Asignacion de Valor a Variable State_in

iButton myObj(&State_in); //construccion de objeto pasando como parametro la direccion de la variable State_in para el apuntador

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(State_in, BIN); //Imprime Valor esperando primer valor igual a 10110 y segundo valor modificado desde clase igual a 10111
  delay(500);
  myObj.setState(0,true);
}

---ibutton.cpp----
#include "iButton.h" //inclucion de archivo .h

iButton::iButton(unsigned int *var) {  //funcion del objeto  con parametro el apuntaor de la variable
  Var = *var; //asignar el valor a Var del valor del apuntador
  *x=*var;
}

void iButton::setState(int posvar,bool data) {

  bitWrite(Var, posvar, data); // modificar la el valor de la Variable Var que es igual a 10110 por 1011
strcpy(*x, &Var); ///no creo que funcione
}

----ibutton.h---

#ifndef iButton_h
#define iButton_h

#include <Arduino.h>

class iButton {
  private:
    unsigned int Var; //Definicion de vairable Var privada
    unsigned int *x;
 public:
    iButton(unsigned int *var); //definicion de funcion de objeto
    void setState(int posvar,bool data);  //definicion de funcion de modificacion de bit
};
#endif
 
Última edición por un moderador:
no creo que sea un problema sencillo pues he visto muchas consultas sobre eso y todos terminan diciendo que se utilice la función extern, pero como mencione solo se puede utilizar variables externas con un nombre especifico.
"extern" no es una función sino un modificador para declarar una variable global a todos los archivos del proyecto (y habría que ponerlo en un .h y no un .c)
Como son variables globales a todo el proyecto, se cae de maduro que cada variable solo puede un nombre único por que el scope es global.
Sigo sin entender cual es el problema....has puesto un montón de líneas de código y en lo ultimo agregado hay un error donde dice:
*x = *var en el constructor de iButton, por que x y var son punteros y vos queres asignar las direcciones apuntadas y no los valores --> x = var
aclaro que no entiendo del todo como funcionan los apuntadores entre el programa y las clases
Eso es el problema.
 
En post #4 tenés la forma en la que tenés que usar el puntero.

Te dejo un ejemplo sencillo en C++ para compilar en gcc que "simula" lo que intentás hacer.

main.cpp:

C++:
#include <iostream>
#include "iButton.hpp"

using namespace std;

unsigned int State_in = 14;

iButton obj(&State_in);

void loop()
{
    cout << "State_in[" << State_in << "]" << endl;
    obj.setState();
    cout << "State_in[" << State_in << "]" << endl;
}

int main()
{
    //while(1)
    //{
        loop();
    //}
    return 0;
}

iButton.hpp:

C++:
#ifndef IBUTTON_HPP
#define IBUTTON_HPP

#include <iostream>

using namespace std;

class iButton
{
    public:
        iButton(unsigned int *var);

        void setState();

    private:
        unsigned int *privateVar;

};

#endif // IBUTTON_HPP

iButton.cpp:

C++:
#include "iButton.hpp"

iButton::iButton(unsigned int *var)
{
    //ctor
    privateVar = var;

    cout << "*var[" << *var << "] - *privateVar[" << *privateVar << "]" << endl;
}

void iButton::setState()
{
    cout << "setState() ..." << endl;

    *privateVar = 56;
}

Cuando ejecutá eso, la salida será la siguiente:

*var[14] - *privateVar[14]
State_in[14]
setState() ...
State_in[56]

Como solo veo una parte de tu proyecto, te puedo recomendar dos cosas:

ALT1:

main.cpp:


C++:
#include <iostream>
#include "iButton.hpp"

using namespace std;

unsigned int State_in = 14;

iButton obj;

void loop()
{
    cout << "State_in[" << State_in << "]" << endl;
    obj.setState(&State_in);
    cout << "State_in[" << State_in << "]" << endl;
}

int main()
{
    //while(1)
    //{
        loop();
    //}
    return 0;
}

iButton.hpp:

C++:
#ifndef IBUTTON_HPP
#define IBUTTON_HPP

#include <iostream>

using namespace std;

class iButton
{
    public:
        iButton();

        void setState(unsigned int *var);
};

#endif // IBUTTON_HPP

iButton.cpp:

C++:
#include "iButton.hpp"

iButton::iButton()
{
    //ctor
}

void iButton::setState()
{
    cout << "setState() - *var[" << *var << "]" << endl;

    *var = 56;
}

Cuando ejecutá eso, la salida será la siguiente:
State_in[14]
setState() - *var[14]
State_in[56]

ALT2:

Finalmente, lo ideal si nos ponemos quisquillosos y evitamos el uso de globales:

main.cpp:

C++:
#include <iostream>
#include "iButton.hpp"

using namespace std;

void loop(iButton *obj, unsigned int *State_in)
{
    cout << "State_in[" << *State_in << "]" << endl;
    obj->setState(State_in);
    cout << "State_in[" << *State_in << "]" << endl;
}

int main()
{
    unsigned int State_in = 14;
    iButton obj;

    //while(1)
    //{
        loop(&obj, &State_in);
    //}
    return 0;
}

E incluso iría más allá y si no necesitara variables dedicadas en la clase iButton, la haría estática.

Editado:

Te agrego el concepto de como funcionan los punteros:

C++:
unsigned int *ptr;
...
ptr <-- Dirección de memoria a la que apunta
*ptr <-- Dato que se encuentra almacenado en la dirección de memoria que apunta

unsigned int var;
...
var <-- Dato que se encuentra almacenado en la variable
&var <-- Dirección de memoria de la variable

Entonces

ptr = &var <-- Es compatible, ptr tomará la dirección de memoria de la variable
*ptr = var <-- Es compatible, el contenido de la dirección a la que apunta el puntero tomará el valor de la variable "var"
 
Última edición:
EUREKA!.... ya funciono... Gracias Cosmefulanito04... tu explicación de como funcionan los punteros es una joya... muy simple y concisa...

esto es lo que queria y funciona..

1720562265298.png

1720562295229.png
1720562411231.png
 

Adjuntos

  • 1720562328635.png
    1720562328635.png
    152.6 KB · Visitas: 3
Quiero imaginar que la variable "Var" en algún momento la modificás, sino no tiene sentido.

Es decir en el constructor asignás la dirección de "State_in" en el puntero "x" y su contenido en la variable "Var". ¿Para qué? si con "x" solo te alcanza, salvo que la variable "Var" la modifiques en algún punto dentro del método "setState()" o con otro método, pero así como está "Var", estaría de más.

Y obviamente el uso de puntero, más allá de que la variable sea global, no tiene sentido, ya que la única modificación que hacés en "setState()" es para asignarle el mismo valor. Si el método "setState()" no modifica la variable, ¿para qué usar punteros?.
 
Atrás
Arriba