Antes de começar, gostaria de fazer imediatamente uma reserva de que o código não foi escrito por mim e retirado daqui . Este programa foi escrito no IDE do Arduino e em conjunto com o arduino pro mini e o nrf24l01 + permite controlar multicopters de brinquedo (com chips de rádio XN297, clones nrf24l01) de qualquer equipamento de controle com saída PPM. Todas as informações sobre multicopter suportados podem ser encontradas no link acima.Decidi reescrever esse código para controlar o mini helicóptero Eachine H8 do equipamento Radiolink AT9. Peço detalhes sob gato.O MSP430 foi escolhido porque possui uma tensão de alimentação de 3,3 volts, a tensão de alimentação nrf24l01 também é de 3,3 volts e, de alguma forma, gosto do MPS430. Dentro do equipamento existem contatos 3V3, OUT, GND, aos quais nos conectaremos.Se não houver desejo de desmontar o equipamento, você poderá conectar ao conector de treinamento, mas a tensão nele = tensão da bateria, para que um estabilizador de tensão seja adicionado ao circuito.Vamos ao código
Primeiro, abra o projeto no IDE Energia (clone do Arduino IDE para MSP430 e outros chips da TI) e tente compilá-lo, mas imediatamente observe um erro de compilação. Este projeto usa bibliotecas adicionais e acesso a registros, e a primeira coisa que você precisa para começar com eles. Então, procedemos a uma análise detalhada.Bibliotecas
Vamos editar o arquivo nRF24_multipro.ino e começar com include'ov. Este projeto usa as bibliotecas atômica e EEPROM.atômico
Nós removemos a linha#include <util/atomic.h>
e na função void update_ppm () removemosATOMIC_BLOCK(ATOMIC_RESTORESTATE)
Em vez de aparelho, escrevemos__disable_interrupt();
e__enable_interrupt();
A função ATOMIC_BLOCK () desativa as interrupções enquanto o código em seu "corpo" é executado e, dependendo do parâmetro, ativa as interrupções ou restaura o valor do sinalizador de interrupção para o estado anterior à chamada da função ATOMIC_BLOCK ().Eeprom
O MSP430 não possui memória EEPROM, mas há memória FLASH e há uma biblioteca MspFlash para trabalhar com ele. Portanto, removemos a linha#include <EEPROM.h>
e adicione a biblioteca MspFlash (Esboço-> Importar Biblioteca ... -> MspFlash), adicione a qual segmento da memória FLASH iremos gravar dados#define flash SEGMENT_D
Na função void selectProtocol (), altere as linhaselse
current_protocol = constrain(EEPROM.read(ee_PROTOCOL_ID),0,PROTO_END-1);
EEPROM.update(ee_PROTOCOL_ID, current_protocol);
em
Flash.write(flash+ee_PROTOCOL_ID, & current_protocol,1);
Removemos completamente a leitura do identificador de protocolo (leia abaixo).No void set_txid (renovação booleana), você precisa fazer um pouco mais do que substituir duas linhas. Na memória FLASH, podemos apenas zero bits. Para definir o valor de 1 nos bits da memória FLASH, é necessário apagar o segmento inteiro (os valores 1 serão gravados nele). Esta função (set_txid) é chamada antes do selectProtocol, portanto, vamos apagar o segmento aqui.Foi: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]);
}
}
}
Tornou-se: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);
}
}
}
Aqui lemos o valor dos identificadores do transmissor e protocolo, apagamos o segmento e, se um comando é dado para atualizar o identificador do transmissor, escrevemos um novo valor, caso contrário registramos o antigo. O byte FLASH da memória com o endereço flash + ee_PROTOCOL_ID permaneceu limpo (0xFF), portanto, não o lemos na função selectProtocol (), mas escrevemos imediatamente o identificador de protocolo.Registros
Primeiro, vamos lidar com os pinos. Neste projeto, é usada uma implementação de software do SPI, na qual macros são usadas para "torcer" as pernas através de registros.Reescreva as definições de pinos#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))
Nos ATMEL MKs, os registros PORTx no MSP430 PxOUT são responsáveis pelo status da saída. Para o status de entrada, os registros PINx e PxIN, respectivamente. A propósito, não há nenhuma função _BV (x) no IDE Energia, portanto, adicione-o você mesmo:#define _BV(val) 1<<val
Na função void setup (), alteramos os valores dos pinos das entradas analógicas para liberar comrandomSeed((analogRead(A4) & 0x1F) | (analogRead(A5) << 5));
por exemplo emrandomSeed((analogRead(A0) & 0x1F) | (analogRead(A1) << 5));
No MSP430, as entradas analógicas A0, A1, A2, ..., A7 correspondem aos pinos P1_0, P1_1, P1_2, ..., P1_7.Ao conectar a mudança de interrupçãoattachInterrupt(PPM_pin - 2, ISR_ppm, CHANGE);
emattachInterrupt(PPM_pin , ISR_ppm, CHANGE);
No Arduino Uno, Nano, Mini, etc. no mega328, apenas 2 pinos (2, 3) estão disponíveis para conectar uma interrupção e, na função attachInterrupt, o primeiro argumento é o número da interrupção, não o pino, como no MSP430. Mais sobre attachInterrupt () .Temporizador
Alteração na configuração de cancelamento ()TCCR1A = 0;
TCCR1B = 0;
TCCR1B |= (1 << CS11);
AtivadoTACTL = TASSEL_2 + ID_3 + MC_2 + TACLR;
É necessário um cronômetro para determinar a duração do pulso no PPM. Nós o configuramos no modo de contagem direta com uma frequência de 2 MHz (frequência de relógio de 16 MHz e um divisor de 8).Na função void ISR_ppm (), mudamoscounterPPM = TCNT1;
TCNT1 = 0;
emcounterPPM = TAR;
TAR = 0;
Os registradores TCNT1 e TAR são contadores temporizados.aleatório ()
Não sei por que, mas a função random () não é chamada sem argumentos na Energia, mas como precisamos de um número aleatório de byte único, substituímos nRF24_multipro.ino e Bayang.ino nos arquivosrandom() & 0xFF;
emrandom(0xFF);
erandom() % 0x42;
emrandom(0x41);
???
E, finalmente, no arquivo MJX.ino, na função void MJX_bind (), adicionamos colchetes à chamada de função mjx_init2;Compilamos o projeto e obtemos uma conclusão bem-sucedida.Código-fonte do projetoCódigo do projeto alteradoPara transferir com sucesso um programa para outra plataforma, é necessário entender o que, como e por que ele é executado neste código, entender os recursos das bibliotecas conectadas, o objetivo dos registros e, no decorrer do trabalho, procurar frequentemente no log de compilação para encontrar erros.Bem, se você faz algo de bom, precisa transferir o projeto para outro ambiente de desenvolvimento, conectar o SPI do hardware e trabalhar apenas com registros, mas essa é uma história completamente diferente.