Master
#include "Wire.h"
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(12,13);
uint8_t I2C_SLAVE_ADDR =0x01;
const bool ResetInError=1;
const int Key_Cambiar_Modo = 1;
const int Key_Confirmar_Modo = 2;
const int Key_Agregar_Modo = 3;
const int Key_Confirmar_Variable=0;
const int Key_Arduino_Ocupado=255;
const String Arduino_Start_1 = "Canal Serial Abierto :)";
String Arduino_Start_2 = "Canal Bluetooth Abierto :)";
const String Arduino_Start_3 = "Canal Wire Abierto :)";
const String Arduino_Start_4 = "Arduino Maesto Iniciado";
const String Arduino_OnRecive = "Recibido : ";
const String Arduino_MovimientoIniciado = "Movimiento Iniciado : ";
const String Arduino_MovimientoTerminado = "Apagando Movimiento";
const String Arduino_ERR_1 = "Err 1 : Algo salio mal cambiando el modo del arduino";
String Arduino_ERR_2 = "Err 2 : Algo salio mal agregando un modo al esclavo";
int Codigos_de_Movimiento[7][12]={
{0,0,0,0,0,0,0,0,1,10,-1,1},
{1,0,1,0,0,1,0,1,4,5000,0,20},
{0,1,0,1,1,0,1,0,6,5000,1,20},
{0,1,0,1,0,1,0,1,8,5000,255,23},
{1,0,1,0,1,0,1,0,10,5000,255,23},
{1,0,1,0,0,1,0,1,12,5000,2,20},
{0,1,0,1,1,0,1,0,14,5000,3,20}
};
uint8_t Motor_Num[8]={2,6,10,11,A0,A1,A2,A3};
uint8_t acutal_Motor_Modes[4]={0,0,0,0};
uint8_t Mode=0;
void setup(){
if(ResetInError){Arduino_ERR_2+="\nEl esclavo se Reiniciara";}
long t1 = millis();
for(int i = 0;i<8;i++){pinMode(Motor_Num[i],OUTPUT);}
Wire.begin();
Serial.begin(9600);
BTSerial.begin(9600);
BTSerial.println(1);
while(true){
if(Iniciar()){break;}
}
}
int asd =0;
void loop(){
if(Serial.available()>0){
int e =(Serial.read());
Mode = e - 48;
Serial.println(Mode);
CambiarMovimiento(Mode);
}
}
void CambiarMovimiento(uint8_t codigo){
//Cambiar Movimiento, Osea salir del estado de reposo a X movimiento
//realizar todo su tiempo y movimiento hasta que se termine o tenga algo delante
//al finaliar detiene todo y vuelve a reposo
if(Iniciar_Movimiento(codigo)){
//Si logra iniciar correctamente el movimiento
long t1 = millis();//Tiempo en el que se inicio el movimiento
int delta=0;//No hace falta explicar lo que delta tiempo significa
uint8_t distancia =0;
while(delta<Codigos_de_Movimiento[codigo][9]){
//Mientras el delta tiempo sea menor que el tiempo de ejecucion del movimeinto hace este loop
if(Codigos_de_Movimiento[codigo][10]==-1){
//Si no usa ningun sensor
//No hace nada
}else{
//Si usa algun sensor conectado
distancia= PedirDatos();
//Pedir la distancia reportada por el sensor
Serial.println("dis = "+String(distancia));
byte distancia1 = (distancia>>(codigo-1))&0b00000001;
if(distancia1 == 0){
//Si la distancia es menor que el minimo permitido
delay(50);
digitalWrite(11,0);
break;
}else{
digitalWrite(11,1);
}
long t2 = millis();
delta = t2-t1;
}
}digitalWrite(11,0);
if(asd>1){
asd--;
distancia = distancia | 0b00000001;
}
Serial.write(asd);
ApagarTodo();
}else{
//Si algo sale
}
}
bool Iniciar_Movimiento(uint8_t codigo){
//Valga la redundancia Este metodo inicia un movimiento
//Devuelve true si el movivimiento se inicio correctamente
//Devuelve false si algo sale mal
if(CambiarModo(Codigos_de_Movimiento[codigo][8]/*Cambia modo del esclavo*/)){
//Iniciar motor 1, si algo falla devuelve falso y apaga todo
if(!Motor(1,Codigos_de_Movimiento[codigo][0],Codigos_de_Movimiento[codigo][1])){ApagarTodo();return false;}
//Iniciar motor 2, si algo falla devuelve falso y apaga todo
if(!Motor(2,Codigos_de_Movimiento[codigo][2],Codigos_de_Movimiento[codigo][3])){ApagarTodo();return false;}
//Iniciar motor 3, si algo falla devuelve falso y apaga todo
if(!Motor(3,Codigos_de_Movimiento[codigo][4],Codigos_de_Movimiento[codigo][5])){ApagarTodo();return false;}
//Iniciar motor 4, si algo falla devuelve falso y apaga todo
if(!Motor(4,Codigos_de_Movimiento[codigo][6],Codigos_de_Movimiento[codigo][7])){ApagarTodo();return false;}
Mode=codigo;
return true;
}else{
return false;
}
}
byte PedirDatos(){
Send_To_Slave(Key_Confirmar_Variable);
//byte res=Obtener_Respuesta(0);
//if(res=Key_Arduino_Ocupado)return 1;
//else return res;
return Obtener_Respuesta(0);
}
bool CambiarModo(uint8_t Codigo){
Send_To_Slave(Key_Confirmar_Modo,10);
//Pide confirmacion en que modo esta el esclvo
if(Obtener_Respuesta(0)!=Codigo){
//Si no esta en el modo que se necesita
Send_To_Slave(Key_Cambiar_Modo,Codigo);
//Cambia el modo del esclavo
Send_To_Slave(Key_Confirmar_Modo,10);
//Pide confirmacion de en que modo esta el esclvo
//1er intento
if(Obtener_Respuesta(0)!=Codigo){
//Si no esta en el modo que se necesita
Send_To_Slave(Key_Cambiar_Modo,Codigo);
//Cambia el modo del esclavo
Send_To_Slave(Key_Confirmar_Modo,10);
//Pide confirmacion de en que modo esta el esclvo
//2do intento
if(Obtener_Respuesta(0)!=Codigo){
//Si no esta en el modo que se necesita
Send_To_Slave(Key_Cambiar_Modo,Codigo);
//Cambia el modo del esclavo
Send_To_Slave(Key_Confirmar_Modo,10);
if(Obtener_Respuesta(0)==Codigo){
return true;
}
}else{
return true;
}
}else{
return true;
}
}else{
return true;
}
/////////////
Serial.println(Arduino_ERR_1);
return false;
}
void ApagarTodo(){
CambiarModo(1);
//Cambia el esclavo a modo reposo
for(int i = 0;i<8;i++){
digitalWrite(Motor_Num[i],false);
//apaga todos los motores
}
for(int i =0;i<4;i++){
acutal_Motor_Modes[i]=0;
//apaga las referencias de los motores en esta variable
}
Serial.println(Arduino_MovimientoTerminado);
Mode=0;
}
bool Motor(uint8_t motor,uint8_t a,uint8_t b){
byte c=a|b<<1;
switch(c){
case 3:return false;
default:acutal_Motor_Modes[motor]=c;
}
switch(motor){
default:return false;
case 1:digitalWrite(Motor_Num[0],a);digitalWrite(Motor_Num[1],b);break;
case 2:digitalWrite(Motor_Num[2],a);digitalWrite(Motor_Num[3],b);break;
case 3:digitalWrite(Motor_Num[4],a);digitalWrite(Motor_Num[5],b);break;
case 4:digitalWrite(Motor_Num[6],a);digitalWrite(Motor_Num[7],b);break;
}
return true;
}
bool Iniciar(){
ApagarTodo();
//Apaga todo para iniciar
for(int i =1; i<(sizeof(Codigos_de_Movimiento)/sizeof(Codigos_de_Movimiento[0]));i++){
//Agrega todos los modos al esclavo
if(!AgregarModo(i-1,Codigos_de_Movimiento[i][8],Codigos_de_Movimiento[i][10],Codigos_de_Movimiento[i][11],true)){return false;}
}
//si todo se agredo retorna true
return true;
}
byte recivedData[5];
bool AgregarModo(int pos,int a, int b, int c,bool master){
Serial.println("Intentando agregar "+String(pos)+" "+String(a)+" "+String(b)+" "+String(c));
Send_To_Slave(Key_Agregar_Modo,pos,a,b,c);
//Manda a agregar el modo a, con el valor b y el sensor c en la posicion pos
Send_To_Slave(Key_Confirmar_Modo,pos);
//Pide la confirmacion del modo guardado en la posicion pos
Obtener_Respuesta(2);
//Obtenemos los valores del metodo guardado en la posicion pos
if(master){
for(int i = 0 ; i<3;i++){
//El metodo se llamara a si mismo 3 veces, pero las 3 repeticiones no tienen permiso
//De llamar 3 veces a si misma porque generarian un bucle infinito y no gracias
if(AgregarModo(pos,a,b,c,0)){return true;}
}
//Si sale del for y llega hasta aca significa que los 3 intentos fallaron
//Antes de retornar falso reinicia el arduino esclavo si la variable ResetInError es true
if(ResetInError){
Send_To_Slave(Key_Cambiar_Modo,0);
EsperarQueReviva();
}
return false;
}else{
if(recivedData[0] ==a&&recivedData[1] ==b){
return true;
}else{
return false;
}
}
}
bool EsperarQueReviva(){
while(!Wire.available()){
Obtener_Respuesta(0);
}
Wire.read();
}
uint32_t Obtener_Respuesta(int t1){
switch(t1){
case 0 :{
uint8_t response;
Wire.requestFrom(I2C_SLAVE_ADDR, sizeof(response));
long t = millis();
while(Wire.available() < 1){
long delta = millis()-t;
if(delta>500){
return 0;
}
}
for(int i = 0;i<((8*t1)+1);i+=8){
response =response +( Wire.read()<<i);
}
//Serial.println("res "+response);
return response;
}
case 1:{
uint16_t response;
Serial.println(sizeof(response));
Wire.requestFrom(I2C_SLAVE_ADDR, sizeof(response));
long t = millis();
while(Wire.available() < 1){
long delta = millis()-t;
if(delta>500){
return 0;
}
}
for(int i = 0;i<((8*t1)+1);i+=8){
response =response |( Wire.read()<<i);
}
return response;
}
case 2:{
uint32_t response;
Wire.requestFrom(I2C_SLAVE_ADDR, sizeof(response));
long t = millis();
while(Wire.available() < 1){
long delta = millis()-t;
if(delta>500){
return 0;
}
}
int i2 =0;
for(int i1 = 0;i1<((8*(sizeof(response)))+1);i1 +=8){
byte rr = Wire.read();
recivedData[i2]=rr;
i2++;
}
return response;
}
case 3:{
uint32_t response;
Serial.println(sizeof(response));
Wire.requestFrom(I2C_SLAVE_ADDR, sizeof(response));
long t = millis();
while(Wire.available() < 1){
long delta = millis()-t;
if(delta>500){
return 0;
}
}
for(int i = 0;i<((8*t1)+1);i+=8){
response =response |( Wire.read()<<i);
}
return response;
}
}
}
void Send_To_Slave(uint8_t data){
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write((byte*)&data, sizeof(data));
Wire.endTransmission();
}
void Send_To_Slave(uint8_t data,uint8_t data1){
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write((byte*)&data, sizeof(data));
Wire.write((byte*)&data1, sizeof(data1));
Wire.endTransmission();
}
void Send_To_Slave(uint8_t data,uint8_t data1,uint8_t data2){
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write((byte*)&data, sizeof(data));
Wire.write((byte*)&data1, sizeof(data1));
Wire.write((byte*)&data2, sizeof(data2));
Wire.endTransmission();
}
void Send_To_Slave(uint8_t data,uint8_t data1,uint8_t data2,uint8_t data3){
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write((byte*)&data, sizeof(data));
Wire.write((byte*)&data1, sizeof(data1));
Wire.write((byte*)&data2, sizeof(data2));
Wire.write((byte*)&data3, sizeof(data3));
Wire.endTransmission();
}
void Send_To_Slave(uint8_t data,uint8_t data1,uint8_t data2,uint8_t data3,uint8_t data4){
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write((byte*)&data, sizeof(data));
Wire.write((byte*)&data1, sizeof(data1));
Wire.write((byte*)&data2, sizeof(data2));
Wire.write((byte*)&data3, sizeof(data3));
Wire.write((byte*)&data4, sizeof(data4));
Wire.endTransmission();
}
Slave
#include "Wire.h"
const int Error_code =0;
const String Advertencia_Sensor_Desconectado="Advertencia: Es posible que este un sensor desconectado";
const String Alerta_Sensor_Desconectado="Alerta: Es posible que tenga un sensor desconectado, mal conectado o los codigos esten cambiados\n Conecte los sensores y reinicie el arduino.";
const int Key_Arduino_Ocupado=255;
volatile bool Cambiando_Modo=false;
volatile bool Agregando_Modo=false;
volatile int Target=0;
bool Ocupado = false;
volatile int keycode=0;
volatile int variable=0;
volatile bool Pidiendo_Modo=false;
volatile int Modo_Solicitado=0;
volatile bool Pidiendo_Modo_Val=false;
volatile byte Modos[7][4]={
{2,0,40,1},
{3,1,40,1},
{4,2,40,1},
{5,3,40,1},
{6,3,40,1},
{8,3,40,1},
{9,3,40,1}
};
//********************************/
byte AccionSolicitada = 0;
bool Sensores_Conectados[4]={1,1,1,1};
int Sensor_Pines[4][3]={
{5,4,6},//adelante
{12,11,13},//atras
{A0,A1,16},//izquierda
{A2,A3,17}//derecha
};
volatile bool Error_Ocurred=false;
volatile byte Modo = 0;
bool Haciendo_Algo = 0;
bool Active = 1;
void setup() {
//CODIGO esclavo
Serial.begin(9600);
Serial.setTimeout(0);
for(int i = 0;i<(4);i++){
pinMode(Sensor_Pines[i][0],OUTPUT);
pinMode(Sensor_Pines[i][1],INPUT);
pinMode(Sensor_Pines[i][2],OUTPUT);
digitalWrite(Sensor_Pines[i][2],1);
}
Serial.println("Se esta iniciando correctamente");
Wire.begin(0x01); //identifico como esclavo 1
Wire.onReceive( receiveEvent); //Declaro Evento
Wire.onRequest(Peticion); //Declaro Evento
Active=1;
}
void loop() {
if(Wire.available()){receiveEvent(1);}
if(Serial.available()){
String a =Serial.readString();
Serial.println(">"+a);
if(a=="/getModes"){
for(int ax = 0;ax<7;ax++){
Serial.println("Modo "+String(ax)+" : "+String(Modos[ax][0]));
}
}else if(a=="/desconectar"){
Modo=0;
}
else if(a=="/reiniciar"){
for(int ax = 0;ax<7;ax++){
Serial.println("Modo "+String(ax)+" : "+String(Modos[ax][0]));
}
}
}
if (Modo== 0){
Serial.println("I am here");
Reset();
}else if(Modo==1){
for (int t = 0; t<4; t++) {
for (int i = 0; i<7; i++) {
AnalizarSensor(i);
}
}
TestearSensores();
}else if(Active){
// AnalizarSensor(Modo-2);
}else{
Error_Ocurred=1;
}
}
byte AnalizarSensor(int s){
Serial.println("Sp"+String(s)+","+String(Sensores_Conectados[ Modos[s][1]]));
if(Modos[s][1]!=255){
if(Sensores_Conectados[ Modos[s][1]]){
byte sensor =0.01723 *Analizar(Sensor_Pines[Modos[s][1]][0],Sensor_Pines[Modos[s][1]][1]);
Serial.println(String(Modos[s][2])+"<"+String(sensor));
if((sensor>Modos[s][2])){
Modos[s][3]=1;
return 1;
}else{
Modos[s][3]=0;
return 0;
}
}else{
Modos[s][3]=0;
return 0;
}
}else{
Modos[s][3]=1;
return 1;
}
}
bool TestearSensores(){
for(int i = 0; i<4;i++){
if(1){
//Si el sensor no devuelve nada lo vuelve a intentar
if(Analizar(Sensor_Pines[i][0],Sensor_Pines[i][1])<=0){
//Si el sensor no devuelve nada lo vuelve a intentar
//Serial.println("Intento 1 del senosor "+String(i+1)+" Fallido");
if(Analizar(Sensor_Pines[i][0],Sensor_Pines[i][1])<=0){
//Si el sensor no devuelve nada lo vuelve a intentar
//Serial.println("Intento 2 del senosor "+String(i+1)+" Fallido");
if(Analizar(Sensor_Pines[i][0],Sensor_Pines[i][1])<=0){
//Cuando ocurren 3 fallos interpreta que el sensor esta desconectado
//Si el arduino se esta ejecutando solamente muestra una advertencia en consola
//Si se esta iniciando no le permite iniciarse
//Serial.println("Intento 3 del senosor "+String(i+1)+" Fallido");
//Serial.println(Advertencia_Sensor_Desconectado);
Sensores_Conectados[i] = 0;
digitalWrite(Sensor_Pines[i][2],0);
}else{
Sensores_Conectados[i] = 1;
digitalWrite(Sensor_Pines[i][2],1);
}
}else{
Sensores_Conectados[i] = 1;
digitalWrite(Sensor_Pines[i][2],1);
}
}else{
Sensores_Conectados[i] = 1;
digitalWrite(Sensor_Pines[i][2],1);
}
}
}
return true;
}
void Reset(){
Wire.endTransmission();
Serial.println("Reset");/*
Cambiando_Modo=false;
Agregando_Modo=false;
Target_Modo_seleccionado=false;
Target=0;
Modo_keycode_annadida=false;
keycode=0;
Modo_variable_val_annadido=false;
variable=0;
active=0;
Pidiendo_Modo=false;
Modo_Solicitado=0;
Pidiendo_Modo_Val=false;
ModoAdelante_V=0;
ModoAdelante[0]=0;
ModoAdelante[1]=0;
ModoAtras_V=0;
ModoAtras[0]=0;
ModoAtras[1]=0;
ModoGirando_V=0;
ModoGirando[0]=0;
ModoGirando[1]=0;*/
Modo =1;Wire.begin(0x01); //identifico como esclavo 1
Wire.onReceive(receiveEvent); //Declaro Evento
Wire.onRequest(Peticion); //Declaro Evento
}
void receiveEvent(int bytes){
byte data[bytes];
for(int i =0;i<bytes;i++){
data[i]=Wire.read();
}
byte AccionEnviada = data[0];
switch(AccionEnviada){
case 0:{//Pedir modo val
AccionSolicitada=(1);
}break;
case 1:{//Cambiar Modo
/*
El error que esta ocurriendo no resuelto creo que es que el maestor
esta mandando la posicion dentro del array, y el esclavo quiere recibir la key
entonces no hace nada
pero despues del escrito vemos
*/
byte ValorSecundario = data[1];//Valor real
int i = 0;
//Serial.println("se quiere cambiar a "+String(ValorSecundario));
Serial.println("Se quiere cambiar a "+String(ValorSecundario));
if(ValorSecundario<2){
Modo =ValorSecundario;
}else{
for(;i<7;i++){
if(ValorSecundario==Modos[i][0]){
Serial.print("Se cambia de "+String(Modo));
Modo = i+2;
Serial.println(" a:"+String(Modo));
break;
}
}
}
}break;
case 2:{//confirmacion de modo
byte ValorSecundario = data[1];//Valor real
if(ValorSecundario==10){
AccionSolicitada=(2);
Modo_Solicitado=10;
}else{
AccionSolicitada=(2);
Modo_Solicitado=ValorSecundario;
//El valor secundario es la posicion del array de modos al que apunta
//Modos[ValorSecundario][key,sensor,valor default]
}
}break;
case 3:{
byte ValorSecundario = data[1];//Valor real
byte ValorTerciario =data[2];//Key
byte ValorCuaternario = data[3];
byte ValorUltimo = data[4];
Modos[ValorSecundario][0]=ValorTerciario;
// Aca seria la key del modo
Modos[ValorSecundario][1]=ValorCuaternario;
//El sensor que usa (0,1,2,3)
Modos[ValorSecundario][2]=ValorUltimo;
//Seria un valor de distancia por default en caso que el sensor este desconectado
// Serial.println("Se añade 1: "
// +String(ValorSecundario)+" "
// +String(Modos[ValorSecundario][0])+" "
// +String(Modos[ValorSecundario][1])+" "
// +String(Modos[ValorSecundario][2]));
}break;
}
}
void EsteMetodoNoHaceNada(int t){
//No hago nada :)
//Nop, efectivamente no hace nada
//pero algo hacia no me acuerdo que era, por eso no lo borro
}
void Peticion(){
// if(Ocupado){Wire.write(Key_Arduino_Ocupado);return;}
//Serial.println("Accion Solicitada : "+String(AccionSolicitada)+" y : "+String(Modo_Solicitado));
if(Error_Ocurred){
Wire.write(0);
Serial.println("Se esta enviando un error");
Error_Ocurred=0;
}else{
switch(AccionSolicitada){
case 1:{
byte rex = AnalizarSensor(Modo-2);
Serial.print("M "+String(rex)+" ");
for(int i = 0; i<7;i++){
Serial.print(","+String(Modos[i][3]));
}
Serial.println();
byte res = 0;
for(int i = 0; i<7;i++){
if(i == (Modo-2)){
res = res | rex<<i;
}else{
res = res | Modos[i][3]<<i;
}
}
Serial.println("Se envia "+ String(res));
Wire.write(res);
//Serial.println(String(Modo)+"distancia es "+String(Modos[Modo-2][2]));
}break;
case 2:{
if(Modo_Solicitado>10){Wire.write(0);break;}
if(Modo_Solicitado==10){
if(Modo<2){
Wire.write((Modo));
}else{
Wire.write((Modos[Modo-2][0]));
// Serial.println("Devolvioendo "+String((Modos[Modo-2][0])));
}
break;
}
else{
// Serial.println("Se pide "+String(Modo_Solicitado)
// +" : "+String(Modos[Modo_Solicitado][0])
// +" "+String(Modos[Modo_Solicitado][1])
// +" "+String(Modos[Modo_Solicitado][2]));
Wire.write(Modos[Modo_Solicitado][0]);
Wire.write(Modos[Modo_Solicitado][1]);
Wire.write(Modos[Modo_Solicitado][2]);
//Se los hay que enviar por separado
//no se puede mandar un uint32_t porque no se que hace
//asi q quedo mas comodo asi
}
}break;
}
}
AccionSolicitada=0;
Modo_Solicitado=0;
}
long Analizar(int triggerPin, int echoPin){
pinMode(triggerPin, OUTPUT); // Clear the trigger
digitalWrite(triggerPin, LOW);
//Sets the trigger pin to HIGH state for 10 microseconds
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
pinMode(echoPin, INPUT);
// Reads the echo pin, and returns the sound wave travel time in microseconds
return pulseIn(echoPin, HIGH);
}
Error en valores de algunas variables en el momento de aplicar la comunicación i2c, estaría muy agradecido si alguien me pudiera dar una manito con este error.
Muchas gracias por pasarte por el post.
Ultima vez actualizado (2/11/21).