Estoy acostumbrado a los bocetos de Arduino con una void setup()
parte que se ejecuta una vez y una void loop()
parte que sigue en bucle. ¿Qué sucede cuando tienes funciones anuladas fuera de la principal void loop()
? ¿Seguirán todos en bucle en paralelo o se ejecutarán uno tras otro? ¿O ciertas funciones nulas solo se ejecutan una vez que se cumplen ciertos criterios (como un ciclo while)?
Por ejemplo, en el siguiente código, ¿cuándo se ejecutarán void receiveData(int byteCount)
las void sendData()
funciones y?
//I2C_test
//This code demonstrates communication via an I2C bus between a raspberry pi and an arduino.
//When the Raspberry pi (master) sends data to the Arduino (slave), the Arduino uses this
//data to control a motor. After the Arduino has recieved data from the master, it then collects
//data from the external environment via a sensor and sends this data back to the Raspberry pi.
#include <Wire.h>
int number = 0; //Declare variables
int val = 0;
void setup() {
//Anything between the curly brackets runs once when the arduino is turned on or reset
pinMode(0, INPUT);
//Set pin 0 as input and 3 as output
pinMode(3, OUTPUT);
Serial.begin(9600);
//Set the data rate for serial transmission at 9600bps
Wire.begin(0x04);
//Initiate the Wire library, join the Arduino as a slave, and specify its 7 bit slave address
Wire.onReceive(receiveData);
//Define callbacks for i2c communication
Wire.onRequest(sendData);
}
void loop() {
//The code between the curly brackets keeps repeating
delay(100);
}
void receiveData(int byteCount) {
while(Wire.available()) {
number = Wire.read();
//Set the variable "number" to the data sent by the master
analogWrite(3, number);
//Write this number to pin 3 (PWM). This controls the motor speed
}
val = analogRead(0);
//Read the voltage on pin 0 (connected to the sensor). Map input voltages between 0 and 5 volts into integer values between 0 and 1023
}
void sendData() {
Wire.write(val);
//Send the data read from the sensor to the master.
}
arduino-uno
i2c
Azul7
fuente
fuente
Respuestas:
Las funciones
setup()
yloop()
son inusuales porque el código Arduino las llama automáticamente. Ninguna otra función se comporta de esta manera.En términos generales, una función nunca se ejecutará a menos que la llame explícitamente usted mismo (por ejemplo, desde adentro
setup()
oloop()
), o le indique a otra parte del programa que la llame. (Hay otras formas de ejecutar funciones, pero eso generalmente implica algunos retoques muy avanzados que es mejor evitar).Por ejemplo,
pinMode()
es una función como cualquier otra. Solo se ejecuta cuando realmente pones algo comopinMode(3, INPUT)
en tu código. En ese punto, se ejecuta una vez, finaliza y luego la función de llamada continúa desde donde se quedó (nunca se ejecuta en paralelo).El código de ejemplo que has publicado es bastante interesante. Mira estas líneas en
setup()
:Estas líneas le dicen al
Wire
objeto que llamereceiveData()
ysendData()
en respuesta a eventos I2C. Lo hace pasando punteros de función que son almacenados y utilizados porWire
.Recomiendo buscar información sobre punteros de función C / C ++ en línea si desea obtener más información al respecto. También te puede interesar explorar la
attachInterrupt()
función de Arduino .fuente
receiveData()
ysendData()
no se ejecutan a menos que se invoquen, ¿por qué se invocan dentro de lavoid setup()
función y no en lavoid loop()
función principal ? ¿Seguramente estas funciones nunca se llamarán a menos que exista la rara posibilidad de que haya un evento i2c mientras el puntero de instrucción todavía está dentro de lavoid setup
función? ¿No sería mejor llamar a estas funciones desde dentro de lavoid loop
función para que cada vez que haya un evento i2c, se llame a la función?void setup()
, se pasan como parámetro deonReceive
yonRequest
, son devoluciones de llamada como dice el comentario. En resumen muy breve: esto le dice al (código de) la biblioteca Wire que llame a estas funciones cuando suceden cosas específicas ( arduino.cc/en/Reference/WireOnReceive , arduino.cc/en/Reference/WireOnRequest ...)twi_init()
cuando llamaWire.begin
. Cuando hay actividad I2C, el µC deja de hacer su tarea actual (a menos que ... no importa por el momento :-) y va en el código de la biblioteca Wire, que luego llama a la función (apropiada, dependiendo de lo que esté sucediendo) que usted registró como devolución de llamada (receiveData
por ejemplo). Una devolución de llamada es el nombre genérico para funciones comoreceiveData
osendData
, son llamadas por un controlador de interrupciones dentro de Wire.¿No es ese caso el que
setup()
se llama una vez yloop()
se llama repetidamente? es decir, hay un invisiblemain()
que podría verse así:Disculpas ya que solo estoy investigando el Arduino y casi no tengo experiencia en C / C ++; Estoy tratando de manejar esta
loop()
situación yo mismo.fuente
init()
que se activan los temporizadoresmillis
,delay
etc. Así queinit()
es para la inicialización general,setup()
es para su inicialización yloop
es, bueno, para bucle. Puedes escribir el tuyomain
si quieres tomar el control total.;
no se requiere después del penúltimo}
:-)No puedo comentar sobre la respuesta de Dee. El código real que se ejecuta en el bucle principal está aquí :
Y sí,
setup()
se llama una vez yloop()
se llama repetidamente (junto con algunas cosas en serie).fuente
Funciona como una función normal, debe llamarse para que tenga sentido. Se llama a loop () / setup () desde una función main () que se compila desde el directorio Arduino y se vincula.
fuente