Go Down

Topic: Proyecto Wifi ESP8266 Como Servidor WEB (Read 4243 times) previous topic - next topic

samu41

Hola muy buenas, estoy haciendo mi TFG con un Arduino Wemos D1 mini pro, el cual incluye Wifi, básicamente estoy utilizando eso y un acelerómetro. Consiste en medir la velocidad de una barra para representarlo luego en un servidor. Sin embargo tengo dos problemas que me gustaría saber si alguien tiene alguna idea/ solución:

Problema 1:

 La cosa es que para calcular la velocidad (e incluso el recorrido que hace) habría que integrar, pero no hay función que exista para integrarla, así que lo que he hecho es hacer el promedio de las aceleraciones durante el tiempo que se está moviendo, le resto 9.8 (que sería la aceleración de la gravedad) y lo multiplico por el tiempo durante el cual la barra se mueve, lo cual se que no es exacto, pero creo que es incluso menos exacto de lo que esperaba, si alguien tiene idea de cómo podría hacerlo mejor estaría agradecido.

Problema 2:

La idea era hacer un servidor web con la wemos, el cual mi tutor dijo que se podría (aunque sea mi tutor no me aporta mucho a la hora del proyecto, me dice sólamente que busque). Y sí, es cierto que se puede hacer un servidor, pero yo quería conectar mi smartphone o portátil a la placa mediante wifi y que lo único que pueda hacer por estar conectado al wifi es estar en el servidor que incorporaría el wifi del wemos. Sin embargo todo lo que he encontrado ha sido que la placa hace de Access Point (AP) pero conectándose a una Wifi y ahí le asigna una dirección IP al servidor y desde el navegador (que está conectado a la wifi de casa, no conectado mediante wifi a la placa) puedes hacer lo que querías.
Yo quisiera saber si se puede hacer que la placa haga literalmente de AP, que al buscar una wifi con tu teléfono aparezca el del arduino, conectarte, y ya en el navegador conectarte al servidor de la propia placa.

Muchas gracias de antemano.

Agradecería mucho algún link o ejemplo en el que haya algo de código para fijarme.

PD: Siento si esto no va aquí, soy nuevo en el foro.

Saludos!

surbyte

Puedes describir el movimiento de la barra?
con un gráfico, por favor. Es una una superficie plana o en plano inclinado?

Me extraña que digas que vas a tomar un promedio. Puedes integrar velocidades, tomando las lecturas de aceleración y usando micros() para saber el tiempo transcurrido. Cada muestra a*t te dará una vi que podrás integrar, usando Simpson.

Lo del servidor Web es de facil resolución. Ya lo veremos. Ahora concéntrate en la medición de velocidad.


samu41

#2
Oct 26, 2017, 03:30 pm Last Edit: Oct 26, 2017, 04:57 pm by surbyte Reason: Errores o códigos con etiqueta de códigos </>
Puedes describir el movimiento de la barra?
con un gráfico, por favor. Es una una superficie plana o en plano inclinado?

Me extraña que digas que vas a tomar un promedio. Puedes integrar velocidades, tomando las lecturas de aceleración y usando micros() para saber el tiempo transcurrido. Cada muestra a*t te dará una vi que podrás integrar, usando Simpson.

Lo del servidor Web es de facil resolución. Ya lo veremos. Ahora concéntrate en la medición de velocidad.


El movimiento de la barra es el del movimiento de un press de banca del gimnasio por ejemplo, es decir, es un empuje vertical completamente (idealmente perpendicular al suelo, sólo que hay alguna pequeña desviación que yo no tengo en cuenta).

A qué te refieres con lo de micros() y Simpson? Ya te digo que sólo llevo 1 mes trabajando con Arduino, me es mas o menos fácil porque he programado bastante en C y es supera parecido, te escribo un poco el código del calculo de la velocidad que he hecho:

Code: [Select]
medida=analogRead(A0);
acc= ((medida/1024.0) *vi -ceroG)/sensibilidad;
float acc2= acc*9.8066;
acc2= abs(acc2);
int iter=0;
suma=0;
Serial.println("Paso1");
if (acc2> (9.8+margen) || acc2<(9.8-margen)){
 inicio=millis();  //Consulta los milisegundos desde que se inició el sketch
     
 while(acc2> (9.8+margen) || acc2<(9.8-margen) ){
   delay(1);
   medida=analogRead(A0);
   acc= ((medida/1024.0) *vi -ceroG)/sensibilidad;
   acc2= acc*9.8066;
   acc2=abs(acc2);
   suma=acc2+suma;
   iter=iter+1;
   Serial.println(acc2);
   delay(1);
}
 
  fin=millis();  //Consulta los milisegundos desde que se inició el sketch
  transcurrido=(fin-inicio);
  Serial.println("tiempoA:");
  Serial.println(transcurrido);
  transcurrido=transcurrido*0.001;//Calcula el tiempo en segundos desde la última lectura
  Serial.println("tiempoB:");
  Serial.println(transcurrido);
  float vel= ((abs(suma-9.8066))/iter)*transcurrido;
  float pos= vel*transcurrido;  
  Serial.println("Aceleración:");
  Serial.println(suma/iter);
  Serial.println("Velocidad:");
  Serial.println(vel);
  Serial.println("Posición:");
  Serial.println(pos);

  delay(2000);

Lucario448

sólo que hay alguna pequeña desviación que yo no tengo en cuenta
¿En la trayectoria o en capturar el tiempo? Para capturar el tiempo con exactitud, tendría que ser mediante interrupciones...

surbyte

#4
Oct 26, 2017, 05:09 pm Last Edit: Oct 26, 2017, 05:13 pm by surbyte
Quote
A qué te refieres con lo de micros() y Simpson?
micros() es la versión que devuelve microseguntos en lugar de millis() para trabajar con mas presición.

Regla de integración de Simpson, es cálculo numeríco. Algo habitual para un programador, es la regla que lleva la integración de un diferencial t al campo discreto usando un Delta t, que es lo que nosotros podemos medir con un microcontrolador.

Yo cuando no veo  bien que vamos a medir me cuesta entender que haces en el código.
La barra no puedes poner una imágen? Usa etiquetas.

Puedes poner además todo el código porque hay variables no definidas como ceroG, etc.
Faltan cosas, setup, librerías si las hubiera.

NOTA:
Códigos van con etiquetas.
Enlaces van con etiquetas
Imagenes van con etiquetas.
Con eso te desenvuelves perfectamente en el foro. Todo esta en las normas 1er hilo de cada sección.

samu41

#5
Oct 26, 2017, 05:12 pm Last Edit: Oct 26, 2017, 05:39 pm by samu41
¿En la trayectoria o en capturar el tiempo? Para capturar el tiempo con exactitud, tendría que ser mediante interrupciones...
En la trayectoria, lo que se quiere medir es la velocidad con la que empujas la barra, para que tengáis una imagen más visual en este vídeo se ven los movimientos que quiero medir VIDEO

La idea es que sea lo más recitilíneo posible, pero como la placa wemos d1 mini pro sólo tiene un pin analógico, tomo como referencia el eje Y, lo ideal sería hacer el módulo de XYZ, pero es un error al que estoy dispuesto a asumir. Lo que genera más dificultad es el "integrar" que al no haber función no se cómo hacerlo. También está el tema del servidor que digo

surbyte

Por favor edita tus post según mis consejos.

Olvida el servidor, primero debes resolver la medición que es la base de tu problema. El servidor y la presentación se resuelve sin problemas.

Que sensor estas usando que lo mides con el AD? me llama la atención!!


samu41

Vale, perdón, justo estaba comentando cuando hiciste el post y no lo vi.

Estoy utilizando un acelerómetro de 3 ejes ADXL335. Los valores esos que me comentas sólo son para poder medir bien los valores con el sensor, valores de datasheet (aunque no eran los ideales). Espero que haya quedado claro lo que quiero medir, es la velocidad a la que levanto la barra en la fase concéntrica (en la que se hace fuerza).

Respecto a Simpson, he hablado con un amigo que está haciendo doble grado de física y matemáticas y me ha dicho que esa regla sólo sirve para interpolar 5 valores, es cierto? porque claro, no me serviría, esto mide mucho valores por segundo.

De todas formas os dejo el código completo.
Code: [Select]
float medida;
float acc;
float vi=3.3;
float ceroG= 1.42;
float sensibilidad= 0.289;
float margen= 0.7; //margen que doy para que no mida nada mas moverlo, si estoy haciendo fuerza la acc!= 9.8, cuando deje de hacer fuerza volverá a ser 9.8
float suma=0; //Iniciamos la suma que luego será el promedio de acc
double transcurrido=0;
unsigned long inicio, fin;  // Mide el tiempo
void setup() {
  // put your setup code here, to run once:
 
  pinMode(A0,INPUT);
  Serial.begin(115200);
 
}

void loop() {
  // put your main code here, to run repeatedly:
 
 medida=analogRead(A0);
 acc= ((medida/1024.0) *vi -ceroG)/sensibilidad; //Aceleración en Gs
 float acc2= acc*9.8066; //Aceleración en m/s^2
 acc2= abs(acc2);
 int iter=0;
 suma=0;
 Serial.println("Paso1");
 if (acc2> (9.8+margen) || acc2<(9.8-margen)){
  inicio=millis();  //Consulta los milisegundos desde que se inició el sketch
     
  while(acc2> (9.8+margen) || acc2<(9.8-margen) ){
    delay(1);
    medida=analogRead(A0);
    acc= ((medida/1024.0) *vi -ceroG)/sensibilidad;
    acc2= acc*9.8066;
    acc2=abs(acc2);
    suma=acc2+suma;
    iter=iter+1;
    Serial.println(acc2);
    delay(1);
 }
   
   fin=millis();  //Consulta los milisegundos desde que se inició el sketch
   transcurrido=(fin-inicio);
   Serial.println("tiempoA:");
   Serial.println(transcurrido);
   transcurrido=transcurrido*0.001;//Calcula el tiempo en segundos desde la última lectura
   Serial.println("tiempoB:");
   Serial.println(transcurrido);
   float vel= ((abs(suma-9.8066))/iter)*transcurrido;
   float pos= vel*transcurrido;   
   Serial.println("Aceleración:");
   Serial.println(suma/iter);
   Serial.println("Velocidad:");
   Serial.println(vel);
   Serial.println("Posición:");
   Serial.println(pos);

   delay(2000);
 }
  delay(50);

}
/* 1g= 9,8066 m/s^2 300mv/g  0G= 1.5V conversor ADC de 10 bits  */

surbyte


samu41

No son movimientos de halterofilia, son de Powerlifting (sentadilla, press de banca y peso muerto). A lo que iba, es cierto que solo se puede usar para 5 datos lo de Simpson?

surbyte

Ve viendo este documento para comparar algoritmos posibles.

samu41

Vale, creo que ya se como hacerlo, lo único que necesito hacer un vector del que no se qué tamaño tiene, ya que depende del numero de muestras que coja, se puede hacer eso?, o en su defecto, cual es el número máximo de posiciones que puede tener un vector en arduino?

surbyte

Eso debes definirlo en funcion de algunas pruebas.
Toma un par de mediciones min max de cuanto tiempo puede llevar el proceso y entonces podrias definir un tamaño de vector que no complique el funcionamiento del sketch y entonces definir cual será la variación de tiempo para tomar las muestras.
En este punto tal vez convenga usar una librería de tiempo como TimeOne u otra.
Con ella puedes determinar en forma precisa cada toma de Aceleración.

Si modificas la rutina levemente y solo llevas la suma de valores, podrias hasta independizarte de la cantidad tomada y solo llevar la cuenta de cuantas muestras has tomado.

Es decir solo haces esto

Code: [Select]
suma += analogRead(A0);   // suma del tipo unsigned long o sea 32 bits
contador++;                               // tal vez un unsigned int
                   

El único problema con esta sugerencia es cuando terminas el muestreo?
Viendo el video observo que en el proceso del levantamiento hay al menos 3 etapas en las que la velocidad queda en reposo.
Partiendo de V = 0 levantas desde el piso hasta la extensión de los brazos.
Luego puedes llevarla a la altura de los hombros y otra vez V = 0
Y por ultimo el momento final hasta arriba de la cabeza y otra vez V = 0.

Tal vez yo este viendo una situación que no corresponda con tu caso.
No se como se llama tecnicamente a ese levantamiento de pesos desde el suelo.

Si tomas la diferencia entre dos valores en un intervalo de tiempo, entonces cuando esta diferencia sea casi nula o x debajo de un umbral estarías en V = 0 o sea en alguna de las 3 situaciones descriptas.

Dime si estoy analizando correctamente tu problema o no?

samu41

Lo que estás teniendo en la cabeza es otra idea, eso es de halterofilia, los levantamientos que yo digo se recogen en este video que puse antes https://www.youtube.com/watch?v=doGyMJoX41w

Lo que hago es medir la fase concentrica, es decir, al principio tendré una aceleración de 9.8 (+-un margen), en el momento en que hago la fase excentrica (bajo) la aceleración se modifica, cuando acabo la fase excéntrica empieza la concéntrica (subo, hago fuerza) y el movimiento acabaría cuando dejo de hacer fuerza, es decir, la aceleración volvería a ser otra vez 9.8

Lo que se me ha ocurrido es decir que el vector tiene un valor muy grande, con un float por ejemplo 1000000, empiezo a almacenar valores, y cuando se sale del ciclo cambio el valor, pongo en codigo para ver si se podría hacer.

Code: [Select]

int i=1000000;
float acc[i];
int j=0;

while (mido aceleración){

acc= analogread(A0);
vector[j]=acc;
j++;
}
if (j<=i){
i=j;
}



De esta forma "reservaría" un montón de posiciones y al final si no las uso las cambio por el número de iteraciones que necesito en verdad. Es algo parecido a reservar memoria con malloc en código C, sólo que en plan chapuza, no se si en arduino existe esa función

Creeis que podría funcionar?

surbyte

#14
Oct 29, 2017, 12:14 am Last Edit: Oct 29, 2017, 12:45 am by surbyte
Primero no puedes tener 1000000 valores. No te da la memoria.
Segundo para que guardar en float algo que lees como unsigned int? Eso es como minimo poco eficiente.

Respecto a la prueba ya lo habias puesto bien y no se porque lo he confundido.
Quote
Si tomas la diferencia entre dos valores en un intervalo de tiempo, entonces cuando esta diferencia sea casi nula o x debajo de un umbral estarías en V = 0 o sea en alguna de las 3 situaciones descriptas.
Esto esta mal. Porque estaras midiendo aceleración y no es la derivada de V que te indica V = 0 sino la integral de aceleración.

Como minimo tendrás que ir llevando algunas muestras y entre ellas integradas de tirán que has terminado.

Respecto a como proceder te propongo algo?
Porque no haces un loggeo de datos, hagamos un código que funcione, que tome datos los almacene y de algun modo podamos luego recuperarlos.
Con esa gráfica luego podremos tomar conclusiones.
Seria interesante que ademas tuviera un par de switches que ilustren los momentos para luego poder tomar decisiones con lo que se observe.

Esos switches no se si los debería tener quien haga la prueba u otra persona.

Yo lo encararía de ese modo.

Acabo de ver el video una vez mas y tomé estos datos desde el inicio de la prueba:
La bajada 5.55 seg y toda la operación fue de 8.07 seg
Asi que tienes 5.55 hacia abajo y 2.52 hacia arriba.

El segundo ejemplo muestra a alguien que tarda 1.66 hacia abajo y  3.40 en total
Bajada 1.66
Subida 1.74

Buscando la RAM del ESP dice tener 96 KiB of data RAM asi que podras destinar gran parte a tu vector.
Cuanto? supongamos unos conservadores 80k
Un entero son 2 bytes asi que son 40k de datos, mas que bien... diría que demasiados.
Todo depende a que tasa los cargues. Supongamos 1 mseg, eso te daria 40000 mseg o 40 seg para tu prueba.
Asi que podrias mejorar las muestras. ya que un tiempo mas logico podria ser de 20 segundos
Supongamos entonces una muestra cada 500 useg para de nuevo tener 40k de datos con un máximo de 20 segundos.

Esto sería un comienzo del código

Code: [Select]
#include <TimerOne.h>                       // https://github.com/PaulStoffregen/TimerOne
#default MUESTRAS    20000
volatile unsigned int vector[MUESTRAS] = {0};
volatile unsigned int i = 0;

void setup(void) {
 
  Timer1.initialize(500);         // 500 useg
  Timer1.attachInterrupt(logger); // tomo datos cada 500 useg
  Serial.begin(9600);
}

void logger(void) {
  vector[i++] = analogread(A0);
}



Falta el loop donde hay que poner algo que lo inicie via un switch, lo detenga (podria ser mismo switch). Algo para levantar los datos y procesarlos en una notebook/PC.




Go Up