Antes de comenzar, me gustaría hacer una reserva inmediata de que el código no fue escrito por mí y tomado de aquí . Este programa está escrito en el Arduino IDE y, junto con arduino pro mini y nrf24l01 +, le permite controlar multicopters de juguete (con chips de radio XN297, clones nrf24l01) desde cualquier equipo de control que tenga una salida PPM. Toda la información sobre multicopter compatible se puede encontrar en el enlace de arriba.Decidí reescribir este código para controlar el mini helicóptero Eachine H8 desde el equipo Radiolink AT9. Pido detalles bajo cat.El MSP430 fue elegido porque tiene un voltaje de suministro de 3.3 voltios, el voltaje de suministro nrf24l01 también es de 3.3 voltios, y de alguna manera me gusta el MPS430. Dentro del equipo hay contactos 3V3, OUT, GND, a los que nos conectaremos.Si no desea desarmar el equipo, puede conectarse al conector de coaching, pero el voltaje en él = voltaje de la batería, por lo que se agrega un estabilizador de voltaje al circuito.Vayamos al código
En primer lugar, abra el proyecto en IDE Energia (clon Arduino IDE para MSP430 y otros chips de TI) e intente compilarlo, pero inmediatamente ve un error de compilación. Este proyecto utiliza bibliotecas adicionales y acceso a registros, y lo primero que necesita para comenzar con ellos. Entonces, procedemos a un análisis detallado.Bibliotecas
Editaremos el archivo nRF24_multipro.ino y comenzaremos con include'ov. Este proyecto utiliza las bibliotecas atómicas y EEPROM.atómico
Quitamos la linea#include <util/atomic.h>
y en la función void update_ppm () eliminamosATOMIC_BLOCK(ATOMIC_RESTORESTATE)
En lugar de llaves escribimos__disable_interrupt();
y__enable_interrupt();
La función ATOMIC_BLOCK () desactiva las interrupciones mientras se ejecuta el código en su "cuerpo" y, según el parámetro, activa las interrupciones o restaura el valor del indicador de interrupción al estado anterior a la llamada a la función ATOMIC_BLOCK ().Eeprom
El MSP430 no tiene memoria EEPROM, pero hay memoria FLASH y hay una biblioteca MspFlash para trabajar con ella. Por lo tanto, eliminamos la línea.#include <EEPROM.h>
y agregue la biblioteca MspFlash (Sketch-> Import Library ... -> MspFlash), agregue a qué segmento de la memoria FLASH escribiremos datos#define flash SEGMENT_D
En la función void selectProtocol (), cambie las líneaselse
current_protocol = constrain(EEPROM.read(ee_PROTOCOL_ID),0,PROTO_END-1);
EEPROM.update(ee_PROTOCOL_ID, current_protocol);
en
Flash.write(flash+ee_PROTOCOL_ID, & current_protocol,1);
Eliminamos por completo la lectura del identificador de protocolo (por qué, lea a continuación).En void set_txid (boolnew), debe hacer un poco más que reemplazar dos líneas. En la memoria FLASH solo podemos cero bits. Para establecer el valor de 1 en los bits de memoria FLASH, debe borrar todo el segmento (luego se escribirán los valores 1). Esta función (set_txid) se llama antes que selectProtocol, por lo que borraremos el segmento aquí.Fue:void set_txid(bool renew)
{
uint8_t i;
for(i=0; i<4; i++)
transmitterID[i] = EEPROM.read(ee_TXID0+i);
if(renew || (transmitterID[0]==0xFF && transmitterID[1]==0x0FF)) {
for(i=0; i<4; i++) {
transmitterID[i] = random() & 0xFF;
EEPROM.update(ee_TXID0+i, transmitterID[i]);
}
}
}
Se convirtió en:void set_txid(bool renew)
{
uint8_t i;
unsigned char p;
for(i=0; i<4; i++) {
Flash.read(flash+ee_TXID0+i,&p,1);
transmitterID[i] =p;
}
Flash.read(flash+ee_PROTOCOL_ID,&p,1);
current_protocol = constrain(p,0,PROTO_END-1);
Flash.erase(flash);
if(renew || (transmitterID[0]==0xFF && transmitterID[1]==0x0FF)) {
for(i=0; i<4; i++) {
transmitterID[i] = random(0xff) & 0xFF;
p = transmitterID[i];
Flash.write(flash+ee_TXID0+i, &p,1);
}
}else{
for(i=0; i<4; i++) {
p = transmitterID[i];
Flash.write(flash+ee_TXID0+i, &p,1);
}
}
}
Aquí leemos el valor de los identificadores del transmisor y el protocolo, borramos el segmento, y si se da un comando para actualizar el identificador del transmisor, escribimos un nuevo valor, de lo contrario, registramos el antiguo. El byte FLASH de la memoria con la dirección flash + ee_PROTOCOL_ID permaneció limpio (0xFF), por lo que no lo leemos en la función selectProtocol (), pero inmediatamente escribimos el identificador de protocolo allí.Registros
Primero, tratemos con los alfileres. En este proyecto, se utiliza una implementación de software de SPI, en la que las macros se utilizan para "mover" las patas a través de los registros.Reescribe las definiciones de pines#define PPM_pin 2
#define MOSI_pin 3
#define SCK_pin 4
#define CE_pin 5
#define MISO_pin A0
#define CS_pin A1
#define ledPin 13
#define PPM_pin P1_5
#define MOSI_pin P2_0
#define SCK_pin P2_1
#define CE_pin P2_2
#define MISO_pin P2_3
#define CS_pin P2_4
#define ledPin P1_4
#define MOSI_on PORTD |= _BV(3)
#define MOSI_off PORTD &= ~_BV(3)
#define SCK_on PORTD |= _BV(4)
#define SCK_off PORTD &= ~_BV(4)
#define CE_on PORTD |= _BV(5)
#define CE_off PORTD &= ~_BV(5)
#define CS_on PORTC |= _BV(1)
#define CS_off PORTC &= ~_BV(1)
#define MISO_on (PINC & _BV(0))
#define MOSI_on P2OUT |= _BV(0)
#define MOSI_off P2OUT &= ~_BV(0)
#define SCK_on P2OUT |= _BV(1)
#define SCK_off P2OUT &= ~_BV(1)
#define CE_on P2OUT |= _BV(2)
#define CE_off P2OUT &= ~_BV(2)
#define CS_on P2OUT |= _BV(4)
#define CS_off P2OUT &= ~_BV(4)
#define MISO_on (P2IN & _BV(3))
En ATMEL MK, los registros PORTx en el MSP430 PxOUT son responsables del estado de salida. Para el estado de entrada, los registros PINx y PxIN, respectivamente. Por cierto, no hay una función _BV (x) en el IDE de Energia, así que agréguela usted mismo:#define _BV(val) 1<<val
En la función void setup () cambiamos los valores de pin de las entradas analógicas para liberarlas conrandomSeed((analogRead(A4) & 0x1F) | (analogRead(A5) << 5));
por ejemplo enrandomSeed((analogRead(A0) & 0x1F) | (analogRead(A1) << 5));
En el MSP430, las entradas analógicas A0, A1, A2, ..., A7 corresponden a los pines P1_0, P1_1, P1_2, ..., P1_7.Al conectar el cambio de interrupciónattachInterrupt(PPM_pin - 2, ISR_ppm, CHANGE);
enattachInterrupt(PPM_pin , ISR_ppm, CHANGE);
En Arduino Uno, Nano, Mini, etc. en mega328, solo 2 pines (2, 3) están disponibles para conectar una interrupción, y en la función attachInterrupt, el primer argumento es el número de interrupción, no el pin como en el MSP430. Más sobre attachInterrupt () .Temporizador
Cambio en la configuración nula ()TCCR1A = 0;
TCCR1B = 0;
TCCR1B |= (1 << CS11);
EnTACTL = TASSEL_2 + ID_3 + MC_2 + TACLR;
Se necesita un temporizador para determinar la duración del pulso en PPM. Lo configuramos en modo de conteo directo con una frecuencia de 2 MHz (frecuencia de reloj de 16 MHz y un divisor de 8).En la función nula ISR_ppm () cambiamoscounterPPM = TCNT1;
TCNT1 = 0;
encounterPPM = TAR;
TAR = 0;
Los registros TCNT1 y TAR son contadores de temporizador.aleatorio ()
No sé por qué, pero la función random () no se llama sin argumentos en Energia, pero como necesitamos un número aleatorio de un solo byte, reemplazamos nRF24_multipro.ino y Bayang.ino en los archivosrandom() & 0xFF;
enrandom(0xFF);
yrandom() % 0x42;
enrandom(0x41);
???
Y finalmente, en el archivo MJX.ino, en la función void MJX_bind (), agregamos corchetes a la llamada a la función mjx_init2;Compilamos el proyecto y obtenemos una conclusión exitosa.Código fuente del proyectoCódigo de proyecto modificadoPara transferir con éxito un programa a otra plataforma, debe comprender qué, cómo y por qué se ejecuta en este código, comprender las características de las bibliotecas conectadas, el propósito de los registros y, en el curso del trabajo, a menudo buscar en el registro de compilación para encontrar errores.Bueno, si hace algo bueno, necesita transferir el proyecto a otro entorno de desarrollo, conectar el SPI de hardware y trabajar solo con registros, pero esta es una historia completamente diferente.