Pasar librería de Arduino a AVRStudio (ATmega)

Ok, entonces, ¿Usaras delay o timer para el tiempo? Lo otro que veo es que agregas half-step, ¿entonces usarías 1 pulso por cada medio paso? De eso podemos colocar en una tabla los valores de los pasos y con un bucle vamos pasando los valores, si está en un solo puerto hacemos Read-Modify-Write para pasar los valores, si usamos timer podemos calcular todo mientras el MCU espera por el tiempo para el siguiente pulso.

Todo esto será rápido siempre que los 4 bits para un motor estén en el mismo puerto y de preferencia uno al lado del otro ocupando el nibble mas significativo para uno y el menor para el otro. Si los pines están por todos lados entonces habra que hacerlo un poco más complejo.
 
hola y muchisimas gracias por tu tiempo
Ok, entonces, ¿Usaras delay o timer para el tiempo? Lo otro que veo es que agregas half-step, ¿entonces usarías 1 pulso por cada medio paso? De eso podemos colocar en una tabla los valores de los pasos y con un bucle vamos pasando los valores, si está en un solo puerto hacemos Read-Modify-Write para pasar los valores, si usamos timer podemos calcular todo mientras el MCU espera por el tiempo para el siguiente pulso.

Todo esto será rápido siempre que los 4 bits para un motor estén en el mismo puerto y de preferencia uno al lado del otro ocupando el nibble mas significativo para uno y el menor para el otro. Si los pines están por todos lados entonces habra que hacerlo un poco más complejo.
bueno la verdad que lo del timer o delay ., no esta definido ., yo se que usando el delay ., estoy "frenando" el micro​
pero si te fijas en la libreria que subi del eje Z ., veras que usa delay ., funciona muy bien y bastente rapido​
aunque con las funciones del "case" ., logro que aparte de lograr el giro ., dejar dos bobinas exitadas ., y asi lograr un "freno de posicion"​
en cuanto a los puertos ., si estan en uno solo ., pero a no olvidarce que los dos ejes son independientes​
pero hay que centrarce en una sola libreria o funcion de motor ., porque son exactamente iguales ( luego se cambia su definicion por X u Y)​
pero bueno eso esta en la idea de cada uno ., y en como dela desarrolle en en su cabeza pero es cuestion de probar ., lo fisico esta armado ., asi que espero tu idea ., para salir de esteembrollo que me hice ., tal vez por estar tan encima ., y no ver la solucion ., desde ya ., muchas gracias por el tiempo e ideas amigo​
 
Desde el sábado se cortó mi línea y no han venido los de la compañía, estoy subiendo esto desde el móvil.

Solo tengo Arduino para programar AVR pero notaras que usa acceso a registros, la única función de Arduino que empleo es la de delay, esta debe ser cambiada desde el #define, intenté emplear _delay_ms(x) pero al compilar arrojaba error, supongo que hace falta declarar algo más primero, pero no uso AVR así que no se como funciona el compilador.

La función debería ser universal, te sirve para cualquier numero de motores, lo que hace es buscar los pines del motor y aislarlos, luego busca en la tabla el índice del paso actual para después entrar en un bucle realizando el desplazamiento el numero de pasos deseados. Como realiza una captura del dato en el puerto para después modificar los bits necesarios y luego enviar esto al puerto nuevamente, no debería perder datos en otros bits.

Por lo pronto solo lo probé en un Arduino Uno, pero como dije, debería ser universal mientras el MCU soporte el acceso directo al registro del puerto ya que este se pasa como puntero.

Lo que creo que podría cambiar para mejorarlo es usar int en lugar de void, así agregamos una condición de error como por ejemplo un sensor de final de carrera y devolvemos el numero de pasos que no avanzó, un return 0 seria igual a que avanzó tidos los pasos.
 

Adjuntos

  • control_de_motor.zip
    1.1 KB · Visitas: 7
Última edición:
hola amigo y muchas gracias ¡¡¡¡¡
Desde el sábado se cortó mi línea y no han venido los de la compañía, estoy subiendo esto desde el móvil.

Solo tengo Arduino para programar AVR pero notaras que usa acceso a registros, la única función de Arduino que empleo es la de delay, esta debe ser cambiada desde el #define, intenté emplear _delay_ms(x) pero al compilar arrojaba error, supongo que hace falta declarar algo más primero, pero no uso AVR así que no se como funciona el compilador.

La función debería ser universal, te sirve para cualquier numero de motores, lo que hace es buscar los pines del motor y aislarlos, luego busca en la tabla el índice del paso actual para después entrar en un bucle realizando el desplazamiento el numero de pasos deseados. Como realiza una captura del dato en el puerto para después modificar los bits necesarios y luego enviar esto al puerto nuevamente, no debería perder datos en otros bits.

Por lo pronto solo lo probé en un Arduino Uno, pero como dije, debería ser universal mientras el MCU soporte el acceso directo al registro del puerto ya que este se pasa como puntero.

Lo que creo que podría cambiar para mejorarlo es usar int en lugar de void, así agregamos una condición de error como por ejemplo un sensor de final de carrera y devolvemos el numero de pasos que no avanzó, un return 0 seria igual a que avanzó tidos los pasos.
bueno ., yo no tengo arduino., y anuque lo tuviera no podria hacer o probar el dato que voy a pasarte​
el caso es que para aquel que tenga arduino ., y tambien quiera programar atmegas ., le conviene instalar el AVRstudio 7​
la interfaz de arduino es la misma ., porque es la oficial ., con la diferencia que trabaja dentro del marco AVRstudio 7​
debajo se abre una ventana donde se va mostrando las alternativas que da el AVRstudio para los demas atmegas​
ahora ., porque no lo hago yo asi ., es muy simple ., mi maquina tiene 256 ram y no soporta a esa vercion​
pero amigo hago lo que puedo con mi vercion 4.13 ., eso si el gcc es el ultimo ( por eso puedo programar hasta los ultimos uC)​
y tranquilo amigo ., ya veremos de a poco los problemas que vallan apareciendo., pero lo mas valorable ., es tu actitud​
siempre es bueno un aporte distinto o con otra mirada ala forma mas si me hago un "matete2 en la cabeza y no puedo salir​
muchas gracias amigo .... ya postiare par mantenerte al tanto
 
Si tuviera internet lo hubiera hecho, pero como dije, tengo desde el sábado la línea muerta y descargar un IDE desde el móvil es demasiado costoso, el problema fue intentar usar _delay_ms(), por lo demas, Arduino se compila mediante GCC, y las librerías de atmel están, inclusive el de tu MCU está ahí, por eso lo hice usando registros directamente al igual que lo realizarias en tu IDE. No creo que te de algún problema el copiar el código directamente.

Además tiendo a usar más los MSP430 y los Tiva C de Texas Instruments, realmente descargar un IDE solo por un chip que en realidad solo compré por referencia y casi no uso, como que tampoco vale mucho la pena.
 
Última edición:
Probado en un TM4C1290NCPDT (Cortex-M4F), funcionó bien, en esta ocación cargué datos a los otros pines y efectivamente estos no se movieron.
La función de delay se cambio desde el define a:
#define __dFun(x) SysCtlDelay(x*120000)
Aquí la función retraza ciclos y tenia el reloj corriendo a 120MHz por eso la multiplicación. Por otra parte solo hubo una advertencia del puerto por el tipo uint8_t ya que en esta arquitectura se considera de 32bits (uint32_t) aunque solo sean 8 pines, de hecho el que use solo tiene 6 pines fisicos y envie datos para 8.
Tambien probe usar #define MotorX(p,t) moveMotor(p, &GPIO_PORTE_AHB_DATA_R, 0, t) para crear una macro que fuera más cómoda de utilizar sin tener que indicar el puerto y offset en cada ocación. Con esto podrias crear MotorX, MotorY, MotorZ, . . . Motorn hasta que te quedes sin puertos.
Por ultimo moví la lectura del puerto al bucle, antes la tenia solo en la busqueda del indice, lo que tenia problemas potenciales con interrupciones. Suponiendo que en cada ciclo hace:
·Letura
·AND
·Asignacion
·Corrimiento de carro
·OR
·Escritura

No deberia tomar mucho ciclos, la otra sería verdaderamente modificar bit a bit en lugar del Leer-Modificar-Escribir. Eso creo que sería cambiando por.
Código:
portData = (motorTable[stepVal] << MotorOffset);
uint8_t btt = 1 << MotorOffset;
uint8_t nobte = 4;
while(nobte){
  if(portData & btt) *MotorPort |= btt;
  else *MotorPort &= ~btt;
  btt << 1;
  nobte--;
}

Como notarás son más pasos a realizar.

Código:
#define __dFun(x) delay(x)  //cambiar por la funcion de delay requerida
const uint8_t motorTable[8] = {0x01,0x03,0x02,0x06,0x04,0x0C,0x08,0x09}; //valores de las bobinas en la secuencia de activación.
/********************
 * halfStep: números de medios pasos a desplazarse, el valor es de 16bits con signo, esto indica el sentido de giro
 * *MotorPort: el puntero a la dirrección del puerto donde se ubican los bits del motor Ej. &PORTD
 * MotorOffset: el desplazamiento de bits en el puerto que ocupa el menor bit del motor, en AVR es equivalente a usar Pxn directamente
 *              Ej. las bobinas ocupan los pines PD4,PD5,PD6 y PD7, el MotorOffset seria simplemente PD4.
 * __delay_val: el valor para la funcion de delay, la función se define por __dFun y debe ser adaptada segun la libreria dispobible,
 *              el tiempo del delay y el metodo se definiran segun esta.
 */
void moveMotor(int16_t halfStep, volatile uint8_t *MotorPort, uint8_t MotorOffset, uint16_t __delay_val){
  uint8_t portData = *MotorPort;
  uint8_t Mask = 0x0F << MotorOffset;
  uint8_t Val = portData >> MotorOffset;
  Val &= 0x0F;
  uint8_t stepVal = 0;
  uint8_t index = 8;
  while(index){
    if(motorTable[--index] == Val){
      stepVal = index;
      break;
    }
  }
  if (halfStep < 0){
    while(halfStep){
      if(stepVal == 0) stepVal = 7;
      else stepVal--;
      portData = *MotorPort & ~(Mask);                  //Leer los bits que deben conservarse
      portData |= (motorTable[stepVal] << MotorOffset); //Modificar con los correspondientes al motor
      *MotorPort = portData;                            //Escribir el nuevo valor al puerto
      halfStep++;
      __dFun(__delay_val);
    }
  }
  else {
    while(halfStep){
      if(stepVal == 7) stepVal = 0;
      else stepVal++;
      portData = *MotorPort & ~(Mask);
      portData |= (motorTable[stepVal] << MotorOffset);
      *MotorPort = portData;
      halfStep--;
      __dFun(__delay_val);
    }
  }
}
 

Adjuntos

  • TivaC.png
    TivaC.png
    31.8 KB · Visitas: 9
Última edición:
gracias amigo Nuyel y pido disculpas por la demora ., pero tengo rota mi compu​
pero he buscado la manera de resolver mi problema y aqui estoy​
compile y me largo error ., pero es un problema de definicion ., aqui te muestro​
capture_08032016_110425.jpg
bueno viendo lo que subiste al post ., aqui es donde yo no entiendo que queres hacer con esa funcion ., que implica ese puerto​
en el .ZIP que subiste esta esta definicion​
PHP:
const uint8_t motorTable[8] = {0x01,0x03,0x02,0x06,0x04,0x0C,0x08,0x09};
alli le esta dando un valor alos puertos (pienso yo) que los definis en hexadecimal ., ¿¿¿ o estoy equivocado ???​
pero en la linea anterior definis esto​
PHP:
#define __dFun(x) delay(x)
tal vez en tu compilador te acepte esta definiciones asi ., pero en el mio no​
eso podria solucionarce creando unas definiciones en una libreria.H ., y agregarlas ala compilacion​
te pregunto esto porque viendo donde me larga el error ( al hacer el traceo) es aca​
PHP:
void setup() { // :poner su código de configuración aquí, para ejecutar una vez
  DDRB = (0x0F << DDB0);
  PORTB = (motorTable[0] << PB0);
}

void loop() { // poner su código principal aquí, para ejecutar repetidamente:
  moveMotor(50, &PORTB, PB0, 250);
  delay(1000);
  moveMotor(-50, &PORTB, PB0, 250);
  delay(1000);
}
calculo ., (es lo que yo creo) . pero puedo no entender bien ., en el setup ., lo que quisiste hacer​
alli declaras un puerto PB0 y por logica en el PORTB ¿¿¿¿ ese pin/port es la entrada del sensor de posicion ???​
si es asi tengo que buscar la manera de definirlo de otra manera ., y darle un lugar en el .H ., asi no me lo acepta​
bueno ese es el principio para ordenar y ponernos de acuerdo​
ahhhhh con respecto a lo que escribiste​
Por otra parte solo hubo una advertencia del puerto por el tipo uint8_t ya que en esta arquitectura se considera de 32bits (uint32_t) aunque solo sean 8 pines,
si ., mi micro acepta esa funcion ., aunque sea de 8 bit (y cristal de 8 MHZ) y corra a 4 MHZ ( por la recepcion de usart)​
hasta aqui te expongo lo que no entiendo ., asi nos vamos poniendo de acuerdo ( y de paso aprendo un poco) ..... gracias amigo​
 
Perdón, pero me mudé para iniciar mis estudios en ingeniería mecatrónica y no tengo internet donde me quedo, bueno, no tengo la PC conmigo en este momento, como mencioné en mi publicación anterior, delay(x) debe ser cambiada por la función de delay que tengas disponible, aparte, también quiero aclarar que lo del primer zip es ub sketch de Arduino, las declaraciones implícitas de las cabeceras las hace el compilador (un sketch es en realidad un archivo en C que es llamado desde el main.c que el compilador incluye implicitamente).

Ahora, estoy en un celular pero intentaré explicar todo detalladamente.

MotorTable es una tabla con los valores (hexadecimal por que se me facilita y el binario no se reconoce en todos los compiladores), tiene la secuencia equivalente necesaria para rotar en orden adecuado las bobinas de un motor a pasos unipolar, solo son los 4 primeros bits los que van escritos.

El primer argumento para la función es el numero de medios pasos para avanzar o retroceder según indique el signo.

El segundo es la dirección del puerto para el puntero, así la función trabaja sobre esta y facilita el funcionamiento, de esta forna podemos controlar tantos motores como necesitemos sin que tengamos que copiar la función o usar C++ para crear una instancia de objeto.

El otro argumento es el desplazamiento de bits del bit menos significativo para controlar el motor, en tu caso, tienes uno ocupando los bits 3-0, el argumento seria el más bajo que es 0, para el segundo ocupas 7-4, en este caso seria 4, este número es para desplazar los valores de la tabla y ajustarlo adecuadamente a los pines que usa el motor.

El ultimo argumento es el tiempo del retraso, pero ojo aquí, dado a que planeaba que fuera más universal, esta función NO está apropiadamente definida en el código que puse de ejemplo, solo Arduino llama así a la función de delay, debe ser cambiada apropiadamente como dije en mi prueba del ARM, en ese compilador con las librerías (TivaWare) la función de delay se especificó usando #define __dFun(x) SysCtlDelay(x*120000), en tu caso usando el Atmel podrías probar con #define __dFun(x) _delay_ms(x), en mi caso al usar Arduino me dio error intentar usar esa función, podrías probar si en tu caso es aceptada.

Para lo último, puedes usar #define para crear una macro para el motor X y Y como indiqué en el ARM, algo como:

#define MotorX(p,t) moveMotor(p, &puerto_del_motor, 0, t)
#define MotorY(p,t) moveMotor(p, &puerto_del_motor, 4, t)

Y así solo usas MotorX(pasos, tiempo);

Se me olvidaba, lo del PB0 lo usé así por que en la librería de Atmel, esa macro corresponde al desplazamiento de bits al pin PB0, lo que es lo mismo al offset requerido por mi función. Como ves, al inicializar el puerto uso en realidad:
Puerto = un valor de la tabla << desplazamiento del pin base
Por eso en el Atmega fue PORTB = (motorTable[0] << PB0); mientras que en el ARM no hice desplazamiento ya que estaba en el pin 0, cuando probé en el Arduino lo hice en varios puertos y con diferentes desplazamientos para confirmar que todo trabajaba bien, el ejemplo que subí simplemente fue cuando el desplazamiento era 0 a modo de ejemplo, como mi función busca el valor del índice correspondiente a las bobinas actuales activadas, es necesario iniciar los pines con un valor de esta, aunque igual puede asignarse manualmente como 0x11 para dos motores en el mismo puerto.
 
Última edición:
hola
Perdón, pero me mudé para iniciar mis estudios en ingeniería mecatrónica y no tengo internet donde me quedo, bueno, no tengo la PC conmigo en este momento, como mencioné en mi publicación anterior, delay(x) debe ser cambiada por la función de delay que tengas disponible, aparte, también quiero aclarar que lo del primer zip es ub sketch de Arduino, las declaraciones implícitas de las cabeceras las hace el compilador (un sketch es en realidad un archivo en C que es llamado desde el main.c que el compilador incluye implicitamente).

Ahora, estoy en un celular pero intentaré explicar todo detalladamente.
muchas gracias amigo ., y menos mal que estas con el celular​
ok ., ya mas o menos entendi ., el formato de trabajo de esa libreria​
voy a tratar de hacer los cambios como lo indicas ., por eso esperaba tu respuesta ., por que si te fijas desdes el principio​
todo lo que hido probando (y publicando)., es totalmente planteado de una manera distinta​
te digo que estuve analizando lo que planteaste y lo veo muchisimo mas logico​
por eso te consulte antes de meter mano mas profundo ., para estar seguro de cual es tu idea ( bien explicada en el anterior post )​
muchas gracias de nuevo !!!!!! y mucha suerte en los cambios y el estudio ¡¡¡¡¡¡​
 
Es que luego no entendí que hacían con tanto código, lo único que recordaba era que querías mover determinado numero de pasos a determinada velocidad y lo del sentido con signo se me hacia más comodo que indicar una función para cada sentido.
 
Atrás
Arriba