Trabajo con vectores (indexado)

¡Hola! Soy nuevo en Arduino, y también en trabajar con sistemas físicos ya que todo lo que llevo programando lo he hecho con software y casos teóricos (no limitado) y ahora que entro en el mundo físico me encuentro con limitaciones (tiempo de ejecución del código, frecuencia de muestreo, variaciones propias del ruido...).

Así que quería saber si podíais echarme un mano: Dispongo de una Arduino DUE y tengo que introducir en un vector muestras que iré recogiendo de los pines analógicos (en conjunto las muestras forman una sinusoide, pero no se trata de muestrear una) lo que pasa es que al comenzar a adquirir datos, siempre hay algunos valores random y estos también se quedan guardados en el vector. Quería saber si hay alguna función ya prediseñada en Arduino que permita buscar un valor concreto del vector (como la función "find" en Matlab).

Muchas gracias.

PD: Vi que hay una función serial.find(), pero como no cogeré datos del puerto serie (los datos se recogerán de los pines analógicos) no creo que sea lo que busco.

grab19 bienvenido al foro Arduino y al mundo físico y de las limitaciónes constantes.
La respuesta es categóricamente No.
Lo mejor que puedes hacer sería una FFT en tiempo real e ir comparando el espectro con uno de referencia y si se aproximan con una desviación menor a 5% diremos que tenemos una coincidencia.
Como la FFT es el análisis espectral de una señal, en todo momento se tiene para cada componente de frecuencia su valor en módulo, por lo tanto se puede comparar con la referencia punto a punto, sean 128, 256 o 512 elementos.
La comparación sería de cada elemento del vector y si su diferencia en valor absoluto esta dentro de un valor porcentual entonces puedes asegurar que ese valor coincide.

Pero el cálculo de cada FFT insume tiempo de modo que como harías para no perder esas señales random que justamente queires detectar?

Espero que la respuesta te sirva y puedas seguir trabajando en tu objetivo.

Hola surbyte, muchas gracias por conestar.

Ya me había planteado lo de FFT pero para otra parte del proyecto en la que tengo que comparar dos señales, por que para esta simplemente tengo que ir comparando constantemente un valor (una muestra) con cada uno de los valores de un señal y no creo que sea necesario hacer una FFT.

Comparar muestras en el dominio del tiempo?
NO estoy de acuerdo pero vamos a lo que tu quieres y luego si no funciona es otro tema.
Quieres comparar vectores, pues cual te parece que es el problema.
Tienes un vector que se va llenado con el muestreo en RT y otro que quieres ubicar.
Pregunto... con que certeza vas a hacerlo. 100% o menos? El vector a buscar debe coincidir con que confianza?

Hola otra vez surbyte, quizás me esté columpiando, pero lo que había pensado hacer es adquirir valores de tensión (capturados mediante los pines analógicos) que variarán desde 0 a 4095 (capturarlos durante un tiempo determinado y almacenarlos en un vector y dejar de capturar mediante este pin durante el resto del código) luego comparar un valor (obtenido de otro pin, un único valor) con cada uno de los componentes del vector creado anteriormente y obtener la posición del mas parecido (aún no me han especificado con que valores de tensión trabajaré así que no sé los valores que tomarán las señales de entrada y no se la resolución con la que contaré así que no puedo hablar del nivel de exactitud), por eso había pensado en hacer un for y barrer todas las componentes del vector hasta encontrar la que más se parezca a la muestra. Por eso mi pregunta inicial era si había alguna función en arduino parecida al "find" de otros lenguajes de programación.

Como dije al inicio, soy bastante nuevo en esto y quisiera que por favor me indicaras si lo que he pensado es factible o me he columpiado bastante.

Saludos.

PD. Creo que antes debí indicar que no es trabajo en tiempo real, tampoco es que el código pueda tardar la vida en ejecutarse, pero el tiempo no es un gran limitador para la función que le daré.

Si tienes toda el tiempo y solo vas a analizar un muestreo sea del tamaño que sea ahi tengo muchas menos restricciones.
Pero es algo que hubiera sido importante que mencionaras al detallar tu idea asi no hablabamos gratuitamente.

Sigo tu idea ahora. Supon por solo dar un número qeu tu muestra tiene 200 valores.
Los barres en un ciclo for (no hay problema) y dime como tomas una coincidencia.

  • solo si es exactamente igual ?
  • Admites un leve desvío?

En el primer caso el simple error del AD hace que sea imposible que encuentres coincidencia.
Toda lectura del ADC tiene un +-1 o 2 LSB eso hace que no puedas considerar esta opción.

Deberías tomar un desvio aceptable a determinar. Entonces si es posible.

Lo que te diré es que la señal a detectar debe terner elementos que la hacen especial, buscar esas cosas suelen ser mas fáciles que intentarlo como tu pretendes.

Hola.
Dos incisos.

  • ¿Cúantas muestras habría que almacenar? Hay que tener en cuenta que cada muestra tomará 2 bytes.
  • ¿Cuánto del periodo de onda almacenarás? A no ser que hablemos de almacenar sólo media onda, se supone que un valor va a encontrar dos coincidencias en un periodo.

surbyte: no es encontrar exactamente el mismo valor, sino más bien como dices, es el que más se le parezca dentro de un desvío predeterminado.

noter: Gracias por mencionar esto del tamaño, es algo que no me había planteado aún (aunque no es importante para esta parte del proyecto, sí que lo será en otra).

Ya conseguí encontrar el valor deseado dentro del vector, gracias por vuestra ayuda.

Ahora me surgen otras dudas ya que han limitado los instrumentos que puedo utilizar, no dispondré de un generador de funciones como me habían dicho al inicio y debo generar una onda sinusoidal de 1kHz o una frecuencia aproximada y una amplitud de 100mv con la placa. Para generarla había pensado en el código que adjunto (tener las muestras ya predefinidas y pasarlas una a una al DAC y con un delay obtener la frecuencia deseada. El código funciona correctamente) pero como la función del programa no es solo generar esta onda, sino que habrán otras instrucciones que consumirán tiempo, la sinusoide no se representa correctamente. Quería saber si había alguna otra forma de generar una señal sinusoidal más sencilla ya que es imperativo generarla y que sea constante, es decir que no se corte por nada, indiferentemente de las operaciones que hagan otras partes del código.

PD: Adjunto el archivo .ino ya que no veo otra forma de postear el código.

sinus_2.ino (762 Bytes)

noter:
Hola.
Dos incisos.

  • ¿Cúantas muestras habría que almacenar? Hay que tener en cuenta que cada muestra tomará 2 bytes.
  • ¿Cuánto del periodo de onda almacenarás? A no ser que hablemos de almacenar sólo media onda, se supone que un valor va a encontrar dos coincidencias en un periodo.

Como yo estuve todo el tiempo pensando en comparar en RT (Real time) no mencioné esto.
Muestrear una señal de 1Khz requiere hacerlo al menos al doble de frecuencia o sea a 2Khz según el teorema de Nyquist.
Entonces 1Khz es un período de 1mseg, y 2Khz son 2 muestras a 500 useg
Pero eso es para una señal PURA de 1Khz, o una señal que descarto posibles componentes de mas alta frecuencia porque justamente estoy muestreando como para garantizar 1Khz.
Generar una señal y luego a su vez compararla con el mismo Arduino me parece como demasiado.
Tal vez pueda funcionar en un DUE pero solo es un comentario sin mas que mi intuición que lo garantice.

Por cierto, el DUE tiene dos DACs asi que se puede generar una senoide de 12Bits y claro esta hacer el resto.

Respecto a lo que pregunte sobre la ejecución de tareas simultaneas, yo mismo me contesto: la DUE incorpora una libreria (scheduler.h) que permite gestionar múltiples tareas a la vez, con lo que este problema queda resuelto (las pruebas que hice resultaron, de momento, correctas). Mucas gracias por vuestra ayuda.

Finalmente, debo muestrear (adquirirla a traves de uno de los pines ADC. Antes se trataba de generarla, por tanto mi duda anterior no tiene nada que ver con esto) una señal sinusoidal de baja frecuencia (1kHz aproximadamente. La señal toma valores desde los 0 a los 2V). Quisiera ver si podíais ayudarme a cambiar la frecuencia de muestreo para obtener 100 muestras por periodo de la señal, es decir, si tengo que configurar algún parámetro, introducir un delay o algo parecido.

Como voy muy verde en lo que se refiere a interactuar con el exterior, probé el código que te asignan como ejemplo para leer datos analógicos del pin A0 y enseñarlos por el monitor serie:

void setup() {
Serial.begin(9600);
}
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue);
delay(1); // delay in between reads for stability
}

Pero en el monitor veo que se cogen pocas muestras, probé modificando el dalay para ver si así se capturaban más muestras del mismo periodo, pero nada, ¿me podríais echar una mano?
Saludos.

Para hacer eso debes,
configurar un timer a la frecuencia de muestreo que detallo a continuación cual será?
configurar el AD para que trabaja en modo libre.
1k => 1mseg de período 100 muestras son 1000 uSeg/100 = 10 uSeg

Todo esto sin interferencia de tu librería scheduler.h

Conseguir una frecuencia de muestreo tan baja es imposible con la placa sin tocar la configuración del micro así que me las apañaré con las 10 muestras que se obtiene.

Ahora una última pregunta, que quizás fue por la que debí comenzar ya que es la más básica de todas: De momento estoy trabajando con el USB (puerto programing) como fuente de alimentación del arduino y claro, cuando termino de trabajar, desconecto el USB. Hay alguna forma de parar la ejecución de código antes de desconectarla?. Por ejemplo dándole al botón de RESET o al de ERASE para no tener que quitarle la fuente de alimentación mientras está ejecutando un programa, o simplemente se desconecta y listo?

Conseguir una frecuencia de muestreo tan baja es imposible con la placa sin tocar la configuración del micro así que me las apañaré con las 10 muestras que se obtiene.

Diras frecuencia de muestro ALTA. 10 useg => 1/10uSeg = 100Khz. Cual es la frecuencia baja?
Y si, tienes razón hay que jugar con el timer pero no es tan complidado.
Te interesa hacerlo asi. Me fijo y te digo como?

Respecto de tu pregunta de desconectar y todo eso. Porque no alimentas el arduino DUE externamente y lo programas y luego retiras el USB sin que nada ocurra?

Si surbyte, tenias razón, me confundí, y quería decir lo que indicaste (alta y no baja). No hace falta que lo mires, ya que con las 10 muestras será suficiente para extraer la información que necesito, pero gracias por ofrecerte a ayudarme.

No lo alimento externamente por que aún no dispongo del adaptador, de hecho es este el que se pidió (http://es.farnell.com/powerpax/sw4311/power-supply-switch-mode-9v/dp/1961443?ost=1961443) podrías indicarme si funcionará?, pone una Vout nominal de 9V así que supongo que irá bien, ya que según la información de la placa, esta acepta una tensión de 7 a 12V.

La duda que yo tenía no era respecto a quitarle el USB, sino a cortarle la alimentación mientras haya un programa ejecutándose, puede que con Arduino esto sea normal, pero con los aparatos que suelo trabajar siempre se debe detener su funcionamiento antes de quitarle la alimentación, y como la placa no es mía, prefiero preguntar antes de cargarme nada.

Saludos.

La duda que yo tenía no era respecto a quitarle el USB, sino a cortarle la alimentación mientras haya un programa ejecutándose, puede que con Arduino esto sea normal, pero con los aparatos que suelo trabajar siempre se debe detener su funcionamiento antes de quitarle la alimentación, y como la placa no es mía, prefiero preguntar antes de cargarme nada.

Quitarla la alimentación cual?
Si le quitas la alimentación el programa deja de funcionar. PUNTO APARTE. Nada mas que discutir o debatir.
Ahora, si lo tienes conectado por USB por donde le subiste el sketch y a la vez alimentado via conector EXTERNO y desconectas el USB no pasa nada.