"Вы читаете о роботах и программировании и думаете: «Было бы здорово сделать что-то подобное самому!» Теми, кем эта идея овладевает чуть больше просто мыслей смотрят кто и как делал своего робота. Читают статьи, смотрят видео. На картинках все понятно. В видеороликах тоже обычно показываются уже готовые продукты, а также сжато показываются технологии их изготовления. И вроде бы то же всё понятно: отпилил, прикрутил, припаял, соединил, запрограммировал вон на той программе вот этим кодом."

воскресенье, 21 марта 2021 г.

Если очень хочется...

 Операции с битовыми масками[1]

Для того чтобы все-таки максимально обезопасить себя от неприятностей при использовании этого метода, можно использовать:

  • для включения (HIGH) бита регистра порта — операцию побитового ИЛИPORTB |= B00100000; (при побитовом ИЛИ ноль не меняет значения бита, а 1 — присваивает биту значение единицы),
  • для выключения (LOW) бита регистра порта — операцию побитового ИPORTB &= ~B00100000; (при побитовом И единица не меняет значения бита, а 0 — присваивает биту нулевое значение).

 

Маску в большинстве случаев удобнее задавать битовым сдвигом вида byte mask = (1 << номер_бита). Таким образом приведенные выше примеры приобретут вид:

PORTB |= (1 << 5);
PORTB &= ~ (1 << 5);

Для присвоения значения сразу нескольким битам с использованием операции битового сдвига можно воспользоваться логическим OR (|):

PORTB |= (1 << 5) | (1 << 2) | (1 << 0); // Присвоить значения 5, 2 и 0 битам
PORTB &= ~ ((1 << 5) | (1 << 2) | (1 << 0)); // Присвоить значения 5, 2 и 0 битам


 Код для управления сервомоторами с поиощью двух джойстиков

#include <Servo.h>
int X = 0;
int Y = 0;
int Z = 0;
int U = 0;
Servo servo_0;
Servo servo_1;
Servo servo_2;
Servo servo_3;
void setup()
{
  DDRB = 0xFF;
  DDRC = 0x00;
  ADCSRA = 0;             // Сбрасываем регистр ADCSRA
  ADCSRB = 0;             // Сбрасываем регистр ADCSRB
  ADMUX |= (1 << REFS0);  // Задаем ИОН
 
 ADCSRA |= (1 << ADPS2); //Биту ADPS2 присваиваем единицу - коэффициент деления 16
  ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0);
 ADMUX |= (0 << REFS1)|(0 << REFS0)|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
  servo_0.attach(8);
  servo_1.attach(9);
  servo_2.attach(10);
  servo_3.attach(11);
}
void loop()
{
L0:;
ADCSRA |= (1 << ADSC);  // Начинаем преобразование
L1:;
if((ADCSRA & (1 << ADIF)) == 0) goto L1;  
int XX = (ADCL|ADCH << 8); // Считываем полученное значение
X = map(XX,0,1023,0,180);
servo_0.write(X);
ADMUX |= (1 << MUX0);   //Переключаемся на А1
ADCSRA |= (1 << ADSC);  // Начинаем преобразование
L2:;
if((ADCSRA & (1 << ADIF)) == 0) goto L2;  
int YY = (ADCL|ADCH << 8); // Считываем полученное значение
Y = map(YY,0,1023,0,180);
servo_1.write(Y);
ADMUX &= ~(1 << MUX0);
ADMUX |= (1 << MUX1);//Переключаемся на А2
ADCSRA |= (1 << ADSC);  // Начинаем преобразование
L3:;
if((ADCSRA & (1 << ADIF)) == 0) goto L3;  
int ZZ = (ADCL|ADCH << 8); // Считываем полученное значение
Z = map(ZZ,0,1023,0,180);
servo_2.write(Z);
ADMUX |= (1 << MUX0);   //Переключаемся на А3
ADCSRA |= (1 << ADSC);  // Начинаем преобразование
L4:;
if((ADCSRA & (1 << ADIF)) == 0) goto L4;  
int UU = (ADCL|ADCH << 8); // Считываем полученное значение
U = map(UU,0,1023,0,180);
servo_3.write(U);
ADMUX &= ~(1 << MUX0); //Переключаемся на А0
ADMUX &= ~(1 << MUX1);
delay(10);
goto L0;
}

Оптимизированный вариант управления

[1]Кравченко Виктор "Тюнинг Arduino или ускоряем работу платы"