Hola todos, llevo ya algún tiempo trasteando con Arduino y estoy con un pequeño proyecto que no se como solucionar.
Se trara de un sensor que al darle un golpe me de en una barra de leds conectados a las salidas digitales la escala de medida del impacto.
En principio el sistema lo he montado con un sensor de fuerza por presion, entre dos planchas con untaco de goma, simplemete aplicando el sketch de ejemplos "barGraph", el resultado es parecido al deseado.
El problema esta que cuando golpéo el sensor la barra de leds sube hasta el valor X que ha producido el golpe, pero no se mantiene.
Como es para un juego quisiera que se quedase marcando el valor maximo hasta que resetease, y también que primero fuese el golpe, y despues puntoa punto se fuesen encendiendo los led hasta llegar a la puntuacion obtenida.
En el sketch que he hecho para esto, lo que falla es que en el impacto, cada vez me coge un valor, ya que el momento de impacto es muy corto, y necesitaría que midiese todo el tiempo del golpe dandome como el valor máximo como resultado.
No se que tal me he explicado, pero cualquier idea al respecto, os la agradecería muchisimo.
no has puesto el codigo que estas usando ni un enlace o datasheet del sensor que estas usando,por lo que me voy a imaginar que si no detecta golpe va a devolver un valor de 0....entonces en el loop tendrias que poner algun condicional que te indicara si el valor de la lectura es mayor que 0 (ha habido impacto )y si no ,mostrar el valor guardado anteriormente,esto lo puedes hacer con un condicional if - else .
Hola Jose, ante todo darte las gracias por tu respuesta, te acalro lo que me comentas.
El sensor que utilizo es un sensor de resistivo que puedes ver en este enlace;
Para tomar la medida lo he colocado como te muestro en el dibujo.
Cuando golpeo sebre él con la mano, en el puerto serie puedeo ver la medida correctamente, te paso tambien el sketch modificado a partir del barGraph de ejemplos de arduino.
Con este programa funciona correctamente cuado das el golpe sobre el sensor los leds se encienden en escala proporcional al golpe pero se apgan una vez cede la fuerza sobre el sensor.
const int analogPin = A0; // Pin del sensor de Fuerza
const int ledCount = 13;
const int analogPinA1 = A1; // Pin Activa Nivel de juego 2
const int analogPinA2 = A2; // Pin Activa Nivel de juego 3
const int OpenDoor0 = 2; // Pin Activa Interrupcion para activar todos los pins
int Level; // Variable para determinar en el map el nivel de juego
int OpenDoor00;
// Numero de leds de lED
int ledPins[] = {
0, 3, 4, 5, 6, 7,8,9,10,11,12,13}; // array en el que estan conectados los led
void setup() {
Serial.begin(9600); // Le enviamos la información, a traves del monitor serie para depurar.
pinMode(OpenDoor0, INPUT);
attachInterrupt(0, OpenDoor, CHANGE); // interrupción
// bucle sobre el array de pins y estableciendolo como salida:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
pinMode(ledPins[thisLed], OUTPUT);
}
}
void loop() {
int sensorReading = analogRead(analogPin);// lectura del sensor:
int Nivel_02 = analogRead(analogPinA1); // lectura de la entrada A1 para determinar si esta activa el nivel de juego 2
int Nivel_03 = analogRead(analogPinA2); // lectura de la entrada A1 para determinar si esta activa el nivel de juego 3
int SensLevel = map(sensorReading, 0, 1023, 0, Level);// mapeado para establecer el rango del sensor FSR
int Nivel_Dos = map(analogPinA1, 0, 1023, 0, 1);// mapeado para usaer la entrada analógica A1 como digital (no se si es necesario hacerlo así).
int Nivel_Tres = map(analogPinA2, 0, 1023, 0, 1);// mapeado para usaer la entrada analógica A2 como digital (no se si es necesario hacerlo así).
Level = 40;// Valor del nivel para el map, en caso de no estar activas las entradas A1 o A2
if (Nivel_02 > 0) { // Condicionantes para establecer el valor del nivel
Level = 40 - 18;
if (Nivel_03 > 0) {
Level = 40 - 25;
}
}
else {
Level = 40;
}
// loop loop sobre el array de Leds
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
//
//
if (thisLed < SensLevel) {//ledlevel
digitalWrite(ledPins[thisLed], HIGH);
}
// apaga todos los leds qu estan en HIGH
else {
digitalWrite(ledPins[thisLed], LOW);
}
}
}
// Funcion interrupción ilumina todos los leds
void OpenDoor() {
OpenDoor00 = digitalRead(OpenDoor0);
do
{
digitalWrite(1, HIGH); //Seg 01
digitalWrite(3, HIGH); // Seg 02
digitalWrite(4, HIGH); // Seg 04
digitalWrite(5, HIGH); // Seg 05
digitalWrite(6, HIGH); // Seg 06
digitalWrite(7, HIGH); // Seg 07
digitalWrite(8, HIGH); // Seg 08
digitalWrite(9, HIGH); // Seg 09
digitalWrite(10, HIGH); // Seg 10
digitalWrite(11, HIGH); // Seg 11
digitalWrite(12, HIGH); // Seg 11
digitalWrite(13, HIGH); // Open Door
}
while (OpenDoor00 == HIGH);
}
El segundo programa que he hecho, mi intención es que una vez dado el golpe los leds se enciendan secuencialmente con un retardo y se queden encendidos hasta resetear la jugada por así decirlo. Este programa como el anterior funciona también, el sensor lee y los led se enciienten como quiero.
El problema esta en la lectrura, me explico; cuando das el golpe, desdee que la mano al impactar con el sensor, empieza a hacer fuerza sobre el mismo, la medida va subiendo hasta su nivel maximo según el golpe, y despues según vas retirando la mano esta medida disminuye.
Como el preograma va leyendo el sensor dependiendo en que momento durante la duracción del impacto lea toma ese valor como bueno. Es decir si en un mismo golpe la lectura la hace cuando empieza el impacto toma un valor bajo, si la medida la lee cuando estas ya retirando la mano es bajo también y si casualmente la hace cuando estas en el momento de mayor presión da su valor correcto.
Mi problema esencialmente consiste en como medir toda la variación que hace el sensor desde que esta en 0 a principio del impacto, hasta que vuenve a 0 despues, y meter en una variable, solo el valor máximo en ese periodo.
El programa que te adjunto doorControl, es el que tengo ahora funcionando y lee el sensor pero claro por los motivos qu te comentaba no va fino ni mucho menos aunque si lee y maraca.
do {
SensLevel = 0;
SensLevelMax = 0;
SensLevelMax2 = 0;
int sensorReading = analogRead(analogPin);
int SensLevel = map(sensorReading, 0, 1023, 0, 500);// mapeo para establecer el nivel de juego
delay(100);
//Serial.print("SensLevel ="); //Imprime en el monitor serie la frase "Analog reading =".
//Serial.println(SensLevel); //Imprime en el monitor serie el valor leido en el sensor.
SensLevelMax = SensLevel;
}
while (SensLevelMax <= 1); // si sens SensLevelMax es mayor que 0 sale del do y segun un varemo de puntuación enciende secuencialmente los leds del puntuacion obtenida
do {
Puntuacion = SensLevelMax;
pin2State = digitalRead(pin2);
Serial.print("Puntuacion ="); //Imprime en el monitor serie la frase "Analog reading =".
Serial.println(Puntuacion); //Imprime en el monitor serie el valor leido en el sensor.
if (Puntuacion <= 10){
delay (timer2);
digitalWrite(1, HIGH); //Seg 01
digitalWrite(3, LOW); // Seg 02
digitalWrite(4, LOW); // Seg 04
Bueno perdonad por el royazo, y muchas gracias de antemano a quienes me podais aportar alguna idéa.
Facilitando las cosas para quien lea este hilo
El sensor de fuerza
En el código SensFuerza.ino usas el pin1
// Funcion interrupción ilumina todos los leds
void OpenDoor() {
OpenDoor00 = digitalRead(OpenDoor0);
do
{
digitalWrite(1, HIGH); //Seg 01
digitalWrite(3, HIGH); // Seg 02
digitalWrite(4, HIGH); // Seg 04
....................... SIGUE aunque no interesa
}
Los pines 0 y 1 se usan para el monitor Serie.
Ten en cuenta que ambas cosas no pueden usarse. No es un error si luego no usas el monitor serie.
No entiendo que hace este código?
Los leds de la barra quedan encendidos siempre y de ahi mi comentario de que no entiendo para que sirve.
tampoco entiendo para que mapeas como digital y no usas un umbral como disparo, aunque lo haces a medio rango de la lectura del ad.
Entonces 1er código, no entiendo bien para que sirve.
Lees niveles y terminas poniendo valores fijos y luego no los graficas.
Código 2.
Bueno acá el error del Serial Monitor es marcado
Defines
int pin1 = 1;
int pin0 = 0;
de ningun modo puede hacer eso con esto definido
Serial.begin(9600);
Acá si estas usando el monitor serie y aunque luego no lo abras habrá un conflicto en los pines.
Otro tema es que tu código puede mejorarse y veré como ayudarte en esa línea.
Vamos a poner las cosas en perspectiva que es lo que debiste hacer al comienzo de tu hilo para los que no sabemos nada de tu juego podamos tener una idea mas acertada.
Algunas cosas ya las has dicho pero otras no directamente.
Dos jugadores usando sensores de fuerza/impacto.
Juego basado en un Arduino UNO
usas 13 leds como BarGraph, esto es NECESARIO si o si? o pueden ser menos?
Tienes un deficit de 2 pines que no puedes usar para el Monitor Serie y para activar los Leds Simultáneamente.
Asi que acá debes decidir si vas a prescindir de 2 leds, usar el monitor Serie o usar Shift Register 595 para manejar esa misma cantidad de Leds o mayor. Con dos 595 y usando solo 3 pines del UNO puedes comandar 16 leds y aumentar en 8 Leds con cada 595 que incorpores.
No entiendo lo que haces con AnalogPin, AnalogPinA1 y AnalogPinA2.
Que debe hacer el juego con cada nivel, me resulta confuso tu lógica de programa
Puedes simplificarse en mucho la forma de presentar la información a la barra de led
De ningún modo deberías ir encendiendo cada led acompañado de un delay porque eso retrasa el funcionamiento de todo el juego y se volverá tedioso y cansador esperar a que responda a los cambios.
Espero tu respuesta
es mas o menos lo que te iba a decir yo .si son indispensables 13 leds y suponiendo que tienes un UNO,los que tienes en los pines 0 y 1 que como bien dice el compañero son usados por el serial,puedes pasarlos a los analogicos A0 y A1 ,cambiando el sensor a otro analogico puesto que tambien pueden ser usados como digitales y ademas el A0 se corresponderia con el numero de pin 14 y A1 con el pin 15 por lo que tendrias los leds de los pines 2 al 15 correlativos que te ira bien para manejarlos con un bucle for.
tambien coincido con Surbyte en lo caotico y rebuscado del codigo cuando en principio el planteamiento del juego parece mas sencillo,yo lo plantearia con un boton de inicio que borra los leds y espera lecturas del sensor .cuando se produce impacto ,sigo leyendo sensor y voy comparando la lectura actual con la anterior ,en el momento que la lectura actual sea inferior ,se deduce que el sensor ha registrado el maximo impacto y el valor obtenido lo mapeas para obtener el numero de leds que han de encenderse .mientras no se vuelva a pulsar el boton de nueva jugada ,la barra mostrara el registro actual.
pero esto es solo una idea.....
Lo primero he arreglado lo de los códigos en en mi post como me sugirió surbyte.
En cuanto al proyecto es lo siguiente un pulsador (el FSR) y una barra de leds, en verdad unos reles que encienden unos led de mayor potencia, cuando el concursante da el golpe, la barra de led sube hasta una medida, si esa medida llega al maximo, un rele (pin13) habre una pequeña puerrta y obtiene así su premio.
Lo de tner tres niveles de juego es por si quien participa es un niño o un adulto.
El Hardware esta hecho y funciona bien, he usado un Arduino Nano metido en un zocalo, esto me plantea un primer problema para cambiar pins de dirección en estos momento, ( por no haberlo pensado antes).
El monitor serie solo lo he abierto para poder ver si el sensor medía y para depuerar, despues en el juego estar desactivado, aun así puedo prescindir de usar el rele conectado al pin 1.
Como biendice Jose lo de mapear el resultado sería lo correcto , pero se me escapan muchas cosas de la funcion map aún.
Bueno lo dicho gracias por todo, y sigo dándole al coco, ya os contare los resultados.
La complegidad de mi código, viene dada por mi inexperiencia y falta de conocimientos en programación con Arduino, evidentemente tengo claro como ha de funcionar el programa haciendo varias lecturas y tomando el valor máximo pero no se como hacerlo, ya que las funciones if... else..., que empleo no consigo hacerlas funcionar, para consegur ese valor .
bueno no importa. No hace falta que justifiques lo que has hecho. Todos empezamos por algo.
Reles que prenden LEDs de mayor potencia! Eso es un sacrilegio en este foro.. si quieres te digo como modificar todo para que uses 16 leds de la potencia que tu me digas (siempre que nos des datos del LED y como los tienes alimentados).
Sigues sin explicar el juego. Lo demas ya lo entendemos.
Explica como quieres graficar
Yo veo esto por ahora y me corriges si estoy mal.
Puntuacion <= 10 es un 0 en los LEDs => todos apagados
11 a 20 un 1 en los Leds. Ilumino 1er led sea el que sea como primero de la barra.
21 a 30 un 3 en los leds. En binario Led1 y Led2 ON y asi
31 a 40 un 7 en los leds. Led1.Led2.Led3 ON
y asi seguimos hasta
41 a 50
51 a 60
61 a 70
71 a 80
81 a 90
91 a 95
a 95 todos ON
Bueno, a ver si este programa funciona mas o menos bien
const byte analogPin = A0; // Pin del sensor de Fuerza
const byte analogPinA1 = A1; // Pin Activa Nivel 2
const byte analogPinA2 = A2; // Pin Activa Nivel 3
const byte pin2 = 2; // Pin Activa Interrupcion abre la puerta
const byte Led[12] = {1,0,3,4,5,6,7,8,9,10,11,12};
const byte PinPuerta = 13;//RL Puerta
int Level;
int SensLevelMax;
int SensLevelMax2;
int SensLevel;
int OpenDoor00;
int Puntuacion;
int Codigo;
int pin2State;
int timer1 = 200;
int timer2 = 500;
int timer3 = 500;
void setup() {
Serial.begin(9600); // Le enviamos la información, a traves del monitor serie para depurar.
pinMode(pin2, INPUT);// interrupción en el pin 2
for (int i=0; i < 12; i++) {
pinMode(i, OUTPUT); // configuramos todos los pines de la Barra de Leds
}
pinMode(PinPuerta, OUTPUT);
//attachInterrupt(0, OpenDoor, CHANGE); // interrupción
}
void loop() {
//Puntuacion=0;
//SensLevelMax=0
int NivelDos = analogRead(analogPinA1);// lee si estan activos los selectores de rango
int NivelTres = analogRead(analogPinA2);
if (NivelDos != 0) {// adjudica un valor a "Level" si esta opción esta seleccionada
Level = 80;
}
else {
if (NivelTres != 0) {
Level = 70;
}
else {
Level = 50; // da el valor de "Level" si ninguna de las anteriores opciones esta seleccionada, es por tanto el Nivel 1 de Juego.
}
}
barraLed(0,LOW);
do {
SensLevel = 0;
SensLevelMax = 0;
SensLevelMax2 = 0;
int sensorReading = analogRead(analogPin);
int SensLevel = map(sensorReading, 0, 1023, 0, 500);// mapeo para establecer el nivel de juego
delay(100);
//Serial.print("SensLevel ="); //Imprime en el monitor serie la frase "Analog reading =".
//Serial.println(SensLevel); //Imprime en el monitor serie el valor leido en el sensor.
SensLevelMax = SensLevel;
} while (SensLevelMax <= 1); // si sens SensLevelMax es mayor que 0 sale del do y segun un varemo de puntuación enciende secuencialmente los leds del puntuacion obtenida
do {
Puntuacion = SensLevelMax;
pin2State = digitalRead(pin2);
Serial.print("Puntuacion ="); //Imprime en el monitor serie la frase "Analog reading =".
Serial.println(Puntuacion); //Imprime en el monitor serie el valor leido en el sensor.
switch (Puntuacion) {
case 0 ... 10: barraLed(1,0);
break;
case 11 ... 20: barraLed(2,0);
break;
case 21 ... 30: barraLed(3,0);
break;
case 31 ... 40: barraLed(4,0);
break;
case 41 ... 50: barraLed(5,0);
break;
case 51 ... 60: barraLed(6,0);
break;
case 61 ... 70: barraLed(7,0);
break;
case 71 ... 80: barraLed(8,0);
break;
case 81 ... 90: barraLed(9,0);
break;
case 91 ... 95: barraLed(10,0);
break;
default: barraLed(11, 1); // Abro la puerta
break;
}
} while (pin2State == LOW);
}
void barraLed(int valor, bool door){
for (int i=0; i<12; i++){
if (i <= valor) {
delay (timer2);
digitalWrite(Led[i], HIGH);
}
else
digitalWrite(Led[i], LOW);
}
// control de puerta
digitalWrite(PinPuerta, door); // Open Door
}
Bueno, debes probarlo, puede tener algún leve error ya que no lo he probado.
ahora esta algo mas prolijo.
Bueno tras unos días de estrés, otra vez por aquí, para varias cosas;
La primera y más importante daros las gracias mil veces por vuestra ayuda.
La segunda es comentar un poco más detalladamente en que ha terminado todo y el porque de cada cosa, ya que creo que de eso también se sacan conclusiones y se aprende, así que respondiendo a algunas de las cuestiones de “surbyte” os comento.
Sobre el Juego: decir, me dedico profesionalmente a los Efectos Especiales para cine y televisión, lo que se conoce técnicamente como SFX, es decir los efectos físicos o mecánicos.
Hago un inciso, para disculparme por no haber podido expresarme anteriormente con mas claridad, pero el tema de los convenios de confidencialidad que tenemos que firmar son muy estrictos.
En este caso teníamos el encargo de hacer un juego que consistía en lo siguiente, un concursante llega hasta un decorado que es una puerta corredera activada por un motor, y al lado tiene una serie de luces en vertical a modo de escala como un termómetro. El participante ha de dar un golpe en una especie de diana de gomaespuma que hay en la puerta, y según la magnitud del golpe se encenderán mas o menos luces de la escala vertical, si se encienden todas, la puerta se abrirá.
En cuanto a pensar que es un sacrilegio lo de usar relés para encender leds, jajajja…… sí, es así ciertamente es así, hasta que trabajas en este mundillo mío, donde el que hace el decorado y pones las luces, primero dice que va a poner leds, pero no sabe cuales hasta cinco minutos antes de entregar la pieza, o al dire de arte se le ocurre en el último momento, que mejor poner bombillas de feria y un molinillo con un motorcito… pues nada tan práctico que los santos, mecánicos, y ruidosos Relés para ir sobre seguro.
Por último, como aportación al foro, esperando que a alguien le sea de utilidad, en mi próximo post pondré con explicación y fotos como coloque el sensor de fuerza con un muy buen funcionamiento en cuanto al resultado.
No os aburro mas con mis historias, un saludo a tod@s
En cuanto a pensar que es un sacrilegio lo de usar relés para encender leds, jajajja…… sí, es así ciertamente es así, hasta que trabajas en este mundillo mío, donde el que hace el decorado y pones las luces, primero dice que va a poner leds, pero no sabe cuales hasta cinco minutos antes de entregar la pieza, o al dire de arte se le ocurre en el último momento, que mejor poner bombillas de feria y un molinillo con un motorcito… pues nada tan práctico que los santos, mecánicos, y ruidosos Relés para ir sobre seguro.
BUeno disculpado porque en ese contexto usar un rele para contemplar las locuras es por lo visto lo mejor.
Y algo mas, no nos aburres, todo contribuye y todo es experiencia para el que lee, el que aporta y el que aprende.