/*
Управление лазером и шаговиком для дальномера.
*/
#define StepFreq 310 //Частота шагов зеркала в герцах
#define motor_X_pin_1 8
#define motor_X_pin_2 9
#define motor_X_pin_3 10
#define motor_X_pin_4 11
#define laserpin 7
#define PosSensor 6
#define PosVCC 5 //Питание для светодиода сенсора
#define PosGND 4 //Земля для светодиода сенсора
int led = 13;
int ii=0;
int id=0;
int inByte[]={0,0,0,0,0,0,0,0}; // Для принятых байтов
volatile int CountByte = 0; // Счетчик принятых
int countwrong=0; //Счетчик неверных длин команд
int MotorPins[] = {motor_X_pin_1, motor_X_pin_2, motor_X_pin_3, motor_X_pin_4};
volatile byte curstep=0; //Текущий "шаг" включения обмоток
volatile byte MOTstep=0; //Текущий шаг мотора
volatile byte USTstep=0; //Заданный шаг мотора
unsigned char timerLoadValue; //Количестов "начальных" тиков таймера
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
pinMode(motor_X_pin_1, OUTPUT);
pinMode(motor_X_pin_2, OUTPUT);
pinMode(motor_X_pin_3, OUTPUT);
pinMode(motor_X_pin_4, OUTPUT);
pinMode(laserpin, OUTPUT);
pinMode(PosSensor, INPUT);
digitalWrite(PosSensor, HIGH); //Подтянем вход датчика вверх
pinMode(PosGND, OUTPUT);
digitalWrite(PosGND, LOW); //поставим ноль питанию датчика
pinMode(PosVCC, OUTPUT);
digitalWrite(PosVCC, HIGH); //поставим единицу (запитаем датчик)
Serial.begin(9600);
//Запускает таймер и получает загружаемое значение таймера.
timerLoadValue=SetupTimer2(StepFreq); //Параметр - частота, Шагов в секунду. Двигатель и больше может...
//Выводит загружаемое значение таймера
Serial.print("Timer2 Load:");
Serial.println(timerLoadValue,HEX);
}
// the loop routine runs over and over again forever:
void loop()
{
if (digitalRead(PosSensor)) {digitalWrite(led, HIGH);}
else {digitalWrite(led, LOW);}
for (int i=0; i<20; i++)
{
// Serial.println (i);
// Serial.println (CountByte);
// delay(100); // wait for a second
if (i==1) //Секция отладки
{
id++;
if (id>31000)
{
id=0;
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
Serial.print ("A_");
Serial.print (ii);
Serial.println (" ");
// Serial.print ("CB=");
// Serial.println (CountByte);
/* Serial.print ("InByte=");
Serial.write (inByte[0]);
Serial.write (inByte[1]);
Serial.write (inByte[2]);
Serial.write (inByte[3]);
//Если первый символ=S тогда следующие два - номер шага
//Serial.println();
*/
ii++;
//delay(1); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
// delay(50); // wait for a second
}
}
if (CountByte>2)
{
CountByte=0;
//Если первый символ=S тогда следующие два - номер шага
//Serial.println();
// Serial.println(inByte[0]);
if (inByte[0]==83) //83 - код "S"
{
Serial.write ("Kom S");
if (inByte[1]==48) //48 - код "0"
{//stepMotor(0);
USTstep--;
Serial.println ("0 ok");}
if (inByte[1]==49) //49 - код "1"
{//stepMotor(1);
USTstep++;
Serial.println ("1 ok");}
}
if (inByte[0]==76) //76 - код "L"
{
Serial.println (i);
Serial.write ("Kom L");
if (inByte[1]==48) //48 - код "0"
{digitalWrite(laserpin, LOW);
Serial.println ("0 ok");}
if (inByte[1]==49) //49 - код "1"
{digitalWrite(laserpin, HIGH);
Serial.println ("1 ok"); }
}
if (inByte[0]==77) //77 - код "M"
{
Serial.write ("Kom M");
USTstep=inByte[1]; //Ставим нужный шаг
Serial.print (USTstep);
Serial.println (" ok");
}
if (inByte[0]==82) //82 - код "R" Начальное позиционирование - дописать
{
Serial.write ("Kom R");
ZeroPos();
Serial.println (" ok");
}
}
}
// Разберемся с "потерянными" командами
if (CountByte) //Если в буфере есть что-то
{
countwrong++; //Увеличиваем счетчик
}
else
{countwrong=0;}
if (countwrong>500)//Если это что-то (типа 1 байт) больше 500 циклов
{
Serial.println ("CountWrong!");
countwrong=0;
CountByte=0;
}
}
void serialEvent() {
//Serial.write ("Event0");
if (Serial.available()) {
digitalWrite(led, HIGH);
//Serial.write ("Event1");
// get the new byte:
inByte[CountByte] = Serial.read();
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inByte[CountByte] == 10) {// '\n', новая строка
CountByte=3;
//Serial.write ("EndString!");
//Serial.write ("EndL!");
}
else{ CountByte++;}
}
}
void stepMotor( int Step) // Step 0 или +1
{
//Serial.println(curstep[Motor]);
int i; //Сдвиг для номеров пинов мотора
if (Step)
{
// Serial.println("StepMotor Step=1");
if (curstep==3)
{curstep=0;}
else
{curstep++;}
}
else
{
// Serial.println("StepMotor Step=0");
if (curstep==0)
{curstep=3;}
else
{curstep--;}
}
switch (curstep) { //переделать, убрать массив с ногами моторов, аменить на дефиненные
case 0: // 1000
digitalWrite(MotorPins[0], HIGH);
digitalWrite(MotorPins[1], LOW);
digitalWrite(MotorPins[2], LOW);
digitalWrite(MotorPins[3], LOW);
break;
case 1: // 0010
digitalWrite(MotorPins[0], LOW);
digitalWrite(MotorPins[1], LOW);
digitalWrite(MotorPins[2], HIGH);
digitalWrite(MotorPins[3], LOW);
break;
case 2: // 0100
digitalWrite(MotorPins[0], LOW);
digitalWrite(MotorPins[1], HIGH);
digitalWrite(MotorPins[2], LOW);
digitalWrite(MotorPins[3], LOW);
break;
case 3: // 0001
digitalWrite(MotorPins[0], LOW);
digitalWrite(MotorPins[1], LOW);
digitalWrite(MotorPins[2], LOW);
digitalWrite(MotorPins[3], HIGH);
break;
}
}
#define TIMER_CLOCK_FREQ 15625.0
//15625 for /1024
//2MHz for /8 prescale from 16MHz
//Установка Таймера2.
//Конфигурирует 8-битный Таймер2 ATMega168 для выработки прерывания
//с заданной частотой.
//Возвращает начальное значение таймера, которое должно быть загружено в TCNT2
//внутри вашей процедуры ISR.
//Смотри пример использования ниже.
unsigned char SetupTimer2(float timeoutFrequency)
{
unsigned char result; //Начальное значение таймера.
//Подсчет начального значения таймера
result=(int)((257.0-(TIMER_CLOCK_FREQ/timeoutFrequency))+0.5);
//257 на самом деле должно быть 256, но я получил лучшие результаты с 257.
//Установки Таймер2: Делитель частоты /8, режим 0
//Частота = 16MHz/1024 = 15625 герц или 64 мкс
//Делитель /1024 дает нам хороший рабочий диапазон
//так что сейчас мы просто жестко запрограммируем это.
TCCR2A = 0;
//TCCR2B = 0<<CS22 | 1<<CS21 | 0<<CS20; //это на 8
TCCR2B = 7;
//Подключение прерывания по переполнению Timer2
TIMSK2 = 1<<TOIE2;
//загружает таймер для первого цикла
TCNT2=result;
return(result); //значение (начальное) счетчика.
}
//Timer2 указатель вектора прерывания по переполнению
ISR(TIMER2_OVF_vect) {
if (MOTstep>USTstep)
{
stepMotor(0);
MOTstep--;
}
if (MOTstep<USTstep)
{
stepMotor(1);
MOTstep++;
}
TCNT2=timerLoadValue;
}
void ZeroPos() //калибровка шаговика
{
USTstep=0; //Уставка - ноль
Serial.print ("USTstep ");
Serial.println (USTstep);
Serial.print ("MOTstep ");
Serial.println (MOTstep);
Serial.print ("PosSensor ");
Serial.println (digitalRead(PosSensor));
while(!digitalRead(PosSensor)) //До срабатывания датчика - шагать
{
MOTstep=1;
// Serial.println ("While");
}
Serial.println ("OK");
}