/********************************************************
В результате на выходе UART получим значения от 1 до 7
соответствующие кнопкам от А до G, при этом пятый бит
должен быль =1 (признак кнопок). И 8 бит от джостика
где старшие 2 бита ось и направление по ней, 5 бит =0,
биты 0-4 величина отклонения от нуля.
********************************************************/
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#define FOSC 16000000UL // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
bool ADC_chanel=0;
char data;
const int zz=1, z=250;//zz - как часто отправляем данные
//Инициализация UART 8 бит данных, 2 стоп бит, бит четности - передатчик
void USART_Init( unsigned int ubrr)
{
//Set baud rate
UBRR0H= (unsigned char)(ubrr>>8);
UBRR0L= (unsigned char)ubrr;
//Enable transmitter
UCSR0B|= (1<<TXEN0);
// Set frame format: 8data, Odd Parity, 2stop bit
UCSR0C|= (1<<UCSZ00)|(1<<UCSZ01)|(1<<UPM00)|(1<<UPM01)|(1<<USBS0);
}
//Инициализация АЦП
void ADC_init (void)
{
//вкл. АЦП(ADEN), разрешение прерывания(ADIE), пределитель 128(ADPS2..ADPS0)
ADCSRA|=(1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
// источник напряжения AVcc(REFS1..REFS0), в данном случае напряжение питания микросхемы
ADMUX|=(1<<ADLAR)|(0<<REFS1)|(1<<REFS0);
//выбор входного канала PORTC.0 (MUX4..MUX0)
ADMUX|=(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
//Запуск преобразования АЦП (одиночное преобразование), для нового измерения повторяем эту строку
ADCSRA|= (1 << ADSC);
}
//вектор прерывания от АЦП
ISR (ADC_vect)
{
//меняем входной канал, инвертируя бит MUX0, переходим с ноги PC0 на PC1 и обратно
ADMUX ^=(1<<MUX0);
//запоминаем в переменную, теперь есть чем выбрать оси Х и У
ADC_chanel=!ADC_chanel;
}
//обработка данных с АЦП
void xy_data(void)
{
//джостик четко стоит на 127 (от 0 до 255) по обоим осям
//чтобы постоянно не отправлять нули и экономить батарейку
//исключаем нулевые значения
if (ADCH!=127)
{
//если ADC_chanel=1 мы измеряем значение по оси х, чтобы это зафиксировать
//будет использоваться 7 (последний) бит посылки =1
if (ADC_chanel==0)
{
//ось х, при движении направо для фиксации события используем 6 бит =1
if (ADCH>130)
{
/*Чтобы освободить те самые 3 старших бита посылки (6 и 7 бит признак оси, 5=0 бит
признак кнопки, 0-4 биты величина отклонения пооси или номер кнопки), пришлось уменьшить
количество значений до 32 (5 бит данных)*/
data = (ADCH-127)/4-1;//максимальное значение 31
//отмечаем в каком направлении происходит движение джостика, в данном случае направо по оси х
data|= (1<<7)|(1<<6);
//отсылаем пакет по UART
UDR0 = data;
}
//ось х, движение налево, 6 бит остается =0
if(ADCH<124)
{
data=(-(ADCH-128))/4-1;
data|= (1<<7);
UDR0 = data;
}
}
else //ось у, 7 бит =0
{
if (ADCH>130) //ось у, движение вперед, 6 бит =1
{
data = (ADCH-127)/4-1;
data|= (1<<6);
UDR0 = data;
}
if(ADCH<124) //ось у, движение назад, 6 бит =0
{
data=(-(ADCH-128))/4-1;
UDR0 = data;
}
}
}
}
//работа с кнопками
void button (void)
{
//на первых битах находится порт UART, а именно ноги TX RX, чтобы не иметь проблем
//сдвинул значение на 2 бита. Все пины порта D за исключением этих двух подтянуты к 1
//и появление на них 0 - признак нажатой кнопки. Ждем нажатия.
switch ( (PIND>>=2) )
{
case 0b00011111://кнопка А и так далее, F, G висят на PB0, PB1
//формат посылки 5 бит=1 признак нажатой кнопки 0-2 бит номер кнопки
UDR0=0b00100001;
_delay_ms(z); //избавляемся от дребезга
break;
case 0b00101111://B
UDR0=0b00100010;
_delay_ms(z);
break;
case 0b00110111://C
UDR0=0b00100011;
_delay_ms(z);
break;
case 0b00111011://D
UDR0=0b00100100;
_delay_ms(z);
break;
case 0b00111101://Е
UDR0=0b00100101;
_delay_ms(z);
break;
}
if ((PINB & (1<<0)) == 0)
{
UDR0=0b00100110;//F
_delay_ms(z);
}
if ((PINB & (1<<1)) == 0)
{
UDR0=0b00100111;//G
_delay_ms(z);
}
}
int main(void)
{
DDRB=0x00;
PORTB=0x00;
DDRD=0x00;
PORTD=0x00;
USART_Init(MYUBRR);
ADC_init();
sei(); //разрешаем прерывания
while (1)
{
//ждем нажатия кнопки
button();
//обрабатываем данные с АЦП, получая направление и величину отклонения по осям
//иначе говоря положение джостика
xy_data();
// повторно запуск преобразования АЦП
ADCSRA |= (1 << ADSC);
//как часто реагируем на работу с джойстиком
_delay_ms(zz);
}
}
Результат нажатия кнопок. Пятый бит всегда =1, это означает, что кнопка нажата, биты с 0 по 2 — номер кнопки.
Движение джойстика вверх. 6-7 бит направление по оси, 5 бит =0 (ни одна кнопка не нажата), 0-4 биты отклонение джойстика от центра. В данном случае движение по оси У вверх, 6-7 биты =01, максимальное значение получается процентов за 5-7 до упора джойстика
https://aliexpress.com/item/item/7-4V-Lipo-Battery-USB-Charger-Cable-For-WLtoys-V912-V913-V915-V262-V323-V333-V666/32513826142.html,searchweb201644_4_79_78_77_82_80_62,searchweb201560_3
https://aliexpress.com/item/item/T500-Smart-Tank-Car-with-Shock-Absorber-Silver-Version-Aluminum-Alloy-Chassis-experiment-platform-servos-controller/32479892107.html
Иными словами будет обзор на шасси, аккумуляторы 18650 — 6 шт, контроллер заряда, блок питания, драйвера двигателя. В идеале все будет ездить :)
Вполне возможно сделаю плату сам, тут уж как получится. Будет это, скорее всего, в феврале месяце.
я тоже немного удивился что с++, раскрыл код, а там честный си )))))
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.