Skip to content

Instantly share code, notes, and snippets.

@z3t0
Created April 12, 2017 06:45
Show Gist options
  • Save z3t0/e3a110138b072467b9a454293035c8a9 to your computer and use it in GitHub Desktop.
Save z3t0/e3a110138b072467b9a454293035c8a9 to your computer and use it in GitHub Desktop.
#include <IRremote.h>
int IRPin = 12; // порт инфракрасного приёмника
IRrecv irrecv(IRPin);
decode_results results;
unsigned long micros_sp = 0;
volatile float sp; // мгновенная скорость
volatile float spAVG = 0; // средняя скорость
float CCSpeedDelta = 0.25; // отклонение от скорости КК для реагирования
unsigned long serviceTime; // временная метка нажатия сервисной кнопки (power off)
int serviceMode = 0; // вариант сервисного режима
int sensorBrPin = 4; // сигнал с педали тормоза
int hallMinPin = 5; // Датчик Холла минимум
int hallMaxPin = 6; // Датчик Холла максимум
int motorPinF = 7; // управление двигателем 1 канал
int motorPinR = 8; // управление двигателем 2 канал
int enabledMotor = 9; // разрешающий сигнал драйверу мотора
int ledHallMaxPin = 10; // светодиод CC_FRW
int buzzerPin = 11; // динамик
int ledHallMinPin = 13; // светодиод CC_REV
int ledCCOnPin = 14; // светодиод CC_On
int acceleratorPin = 5; // сигнал с датчика БДЗ (аналоговый)
boolean ccActive = 0; // активность КК
int timePeriod = 1000;
unsigned long timeMotorStop = 0; // время остановки мотора
int SpeedFail = 0; // счётчик нарушений скорости для безопасности
int SpeedReduction = 0; // счётчик кол-ва последовательного снижения скорости
//int SpeedReduction2 = 0; // счётчик кол-ва последовательного снижения скорости
int SpeedIncrease = 0; // счётчик кол-ва последовательного увеличения скорости
float CCSpeed = 0; // скорость КК
const int CCSpeedMin = 5; //
const int CCSpeedMax = 5; //
int CurrDZ;
int DZPosMin; // минимальное положение ДЗ ~95
int DZPosMax; // максимальное положение ДЗ ~750
float OldSpeed = 0; // скорость прошлого замера
float SpeedUp = 0; // ускорение
//float SpeedOld = 0; // старая скорость в расчёте ускорения
float CalcSpeedUp = 0; // расчётное ускорение
int CSDK = 15; // коэффициент резкости расчётного ускорения (рекомендуется от 15 до 30, чем больше тем резче разгон)
unsigned long timeOldSpeed = 0; // время замера прошлой скорости
void myTone(int hertz,int longs) {
unsigned long startTime = millis() + longs;
float period = 1000000 / hertz;
while (millis() <= startTime)
{
digitalWrite(buzzerPin, HIGH);
delayMicroseconds(period / 2);
digitalWrite(buzzerPin, LOW);
delayMicroseconds(period / 2);
}
}
void indicator(float val) {
myTone(1500, 100);
digitalWrite(ledHallMinPin, LOW);
digitalWrite(ledCCOnPin, LOW);
digitalWrite(ledHallMaxPin, LOW);
delay(2000);
int cel;
String str;
str = String(val);
for (int i=0; i < str.length(); i++){
if (str[i] != '.') {
cel = str[i] - 48;
if (cel == 0) {
digitalWrite(ledHallMinPin, HIGH);
delay(500);
digitalWrite(ledHallMinPin, LOW);
delay(500);
}
else
{
for (int j=1; j <= cel; j++) {
digitalWrite(ledHallMaxPin, HIGH);
delay(500);
digitalWrite(ledHallMaxPin, LOW);
delay(500);
}
}
}
else
{
digitalWrite(ledCCOnPin, HIGH);
delay(500);
digitalWrite(ledCCOnPin, LOW);
delay(500);
}
myTone(1500, 100);
delay(1000);
}
serviceTime = millis();
}
void speedometr() { // Определяем текущую скорость
sp = (float)(1500000.0 / (micros() - micros_sp)); //600000.0 - 6 имп./м 1000000.0 - 10 имп./м и т.д
micros_sp = micros();
}
void setup() {
pinMode(motorPinF, OUTPUT);
digitalWrite(motorPinF, LOW);
pinMode(motorPinR, OUTPUT);
digitalWrite(motorPinR, LOW);
pinMode(enabledMotor, OUTPUT);
digitalWrite(enabledMotor, HIGH); // подаём разрешающий сигнал на драйвер
pinMode(hallMinPin, INPUT);
digitalWrite(hallMinPin, HIGH);
pinMode(hallMaxPin, INPUT);
digitalWrite(hallMaxPin, HIGH);
pinMode(sensorBrPin, INPUT);
digitalWrite(sensorBrPin, HIGH);
pinMode(buzzerPin, OUTPUT);
pinMode(ledCCOnPin, OUTPUT);
pinMode(ledHallMaxPin, OUTPUT);
pinMode(ledHallMinPin, OUTPUT);
digitalWrite(2, HIGH);
attachInterrupt(0, speedometr, RISING); // Прерывание INT0 на 4 ноге ATMega328. Подаем сигнал с датчика скорости, ограничив амплитуду сигнала до 4,5 В
// делителем или оптопарой и притянув вход к земле
// attachInterrupt(1, multiINTO, LOW); // Прерывание INT0 на 5 ноге ATMega328. Подаем сигнал с датчиков Hall (max, min), break, Sens_A/B (вызывает прерывание, когда на порту LOW)
analogReference(DEFAULT); // пока считаем, что диапазон измеряемых значений от ДЗ от 0 до +5В, потом возможно придётся разбираться!
// Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
spAVG = 20;
}
void motorMode(int mode) { // управляем приводом. задаём направление вращения или выключаем
// останавливаем мотор
digitalWrite(motorPinF, LOW);
digitalWrite(motorPinR, LOW);
switch (mode) {
case 0: // остановить мотор
// мотор остановлен на входе
break;
case 1: // крутим вперёд
if (digitalRead(hallMaxPin) != 0) {
digitalWrite(motorPinF, LOW);
digitalWrite(motorPinR, HIGH);
}
break;
case 2: // крутим назад
if (digitalRead(hallMinPin) != 0) {
digitalWrite(motorPinF, HIGH);
digitalWrite(motorPinR, LOW);
}
break;
}
}
void buzzGo(int mode) {
switch (mode) {
case 1: // получен известный код IR приёмником
myTone(1500, 100);
break;
case 2:
myTone(1500, 100);
break;
case 5: // включаем КК
break;
case 9: // левый код IR приёмника
break;
case 10: // отключение КК
break;
}
}
int ReadDZ_AVG(){
int i;
int sval = 0;
for (i = 0; i < 100; i++){
sval = sval + analogRead(acceleratorPin);
}
sval = int(sval / 100); // среднее
return sval;
}
float ReadSP_AVG() {
float ssp;
int i = 0;
float sval = 0;
unsigned long timeEnd;
timeEnd = millis() + 100;
while (millis() < timeEnd) {
ssp = sp;
if (ssp < 200) {
sval = sval + ssp;
i = i + 1;
}
}
sval = sval / i; // среднее
return sval;
}
void ccOFF() { // отключаем КК, сбрасываем газ
motorMode(0);
ccActive = false; // снимаем статус активности КК
timeMotorStop = millis() + 10000;
motorMode(2);
while (digitalRead(hallMinPin) != 0 && millis() < timeMotorStop) { //пока ДЗ не встанет в минимум вращаем в обратку привод или временное ограничение 5 секунд
// delay(3);
}
motorMode(0);
// buzzGo(10);
}
void setDZ(int tmpDZ) { // Устанавливаем ДЗ в конкретное положение
timeMotorStop = millis() + 2000;
if (ReadDZ_AVG() < tmpDZ){
timeMotorStop = millis() + 2000;
while (digitalRead(hallMinPin) == 0 && millis() < timeMotorStop){ // если привод в минимуме вытягиваем провисание
motorMode(1);
delay(5);
// motorMode(0); // пауза для плавности восстановления дросселя
// delay(5); // задержка для плавности восстановления дросселя
// контроль вмешательства человека в управление дросселем
if ((digitalRead(hallMinPin) == 0 && digitalRead(motorPinF) == 1 && digitalRead(motorPinR) == 0) || (digitalRead(hallMaxPin) == 0 && digitalRead(motorPinF) == 0 && digitalRead(motorPinR) == 1)) {
motorMode(0);
return;
}
if (digitalRead(sensorBrPin) == 0) { //нажата педаль тормоза отключаем КК
ccOFF();
return;
}
}
timeMotorStop = millis() + 2000;
while (digitalRead(hallMaxPin) != 0 && ReadDZ_AVG() < tmpDZ && millis() < timeMotorStop) { // временное ограничение 5 секунд
// Serial.println(ReadDZ_AVG());
motorMode(1);
delay(8);
motorMode(0); // пауза для плавности восстановления дросселя
delay(55); // задержка для плавности восстановления дросселя
// контроль вмешательства человека в управление дросселем
if ((digitalRead(hallMinPin) == 0 && digitalRead(motorPinF) == 1 && digitalRead(motorPinR) == 0) || (digitalRead(hallMaxPin) == 0 && digitalRead(motorPinF) == 0 && digitalRead(motorPinR) == 1)) {
motorMode(0);
return;
}
if (digitalRead(sensorBrPin) == 0) { //нажата педаль тормоза отключаем КК
ccOFF();
return;
}
}
}
else
{
timeMotorStop = millis() + 2000;
while (digitalRead(hallMinPin) != 0 && ReadDZ_AVG() > tmpDZ && millis() < timeMotorStop) { // временное ограничение 5 секунд
motorMode(2);
delay(5);
motorMode(0); // пауза для плавности
delay(55); // задержка для плавности
// контроль вмешательства человека в управление дросселем
if ((digitalRead(hallMinPin) == 0 && digitalRead(motorPinF) == 1 && digitalRead(motorPinR) == 0) || (digitalRead(hallMaxPin) == 0 && digitalRead(motorPinF) == 0 && digitalRead(motorPinR) == 1)) {
motorMode(0);
// buzzGo(9);
return;
}
if (digitalRead(sensorBrPin) == 0) { //нажата педаль тормоза отключаем КК
ccOFF();
return;
}
}
}
motorMode(0);
}
void ccON() {
int ssp;
ssp = sp;
if (ssp > 20 && ssp < 130) {
SpeedReduction = 0;
OldSpeed = ssp; // запоминаем текущ. скорость как старую
timeOldSpeed = millis();
spAVG = ssp;
// SpeedOld = ssp;
// управляем ledCCOnPin
digitalWrite(ledCCOnPin, HIGH);
setDZ(CurrDZ + 5);
ccActive = true;
buzzGo(5);
}
else
buzzGo(10);
}
void loop() {
spAVG = ReadSP_AVG();
CurrDZ = ReadDZ_AVG();
if (DZPosMin < 20) {
DZPosMin = CurrDZ;
}
if ((millis() > 900) && (millis() < 1100)) {
buzzGo(1);
}
if (irrecv.decode(&results)) {
// 0xFD40BF - CH+ *
// 0xFD807F - CH- *
// 0xFD20DF - EQ *
// 0xFD50AF - >>| *
// 0xFD906F - |<< *
// 0xFDA05F - V-
// 0xFD609F - V+
// 0xFD00FF - >/||
// 0xFDE21D - call off
// 0xFDA25D - call on
// 0xFD9867 - power *
switch (results.value) {
case 0xFD9867: // кнопка калибровки // 0xFD9867 - power
buzzGo(1);
ccOFF();
if (!ccActive && digitalRead(hallMinPin) == 0) {
serviceTime = millis();
}
break;
case 0xFD20DF: // включаем/выключаем круиз // 0xFD20DF - EQ
buzzGo(1);
if (!ccActive) {
ccON();
CCSpeed = spAVG;
}
else {
ccOFF();
}
break;
case 0xFD50AF: // Увеличить скорость КК на 4 // 0xFD50AF - >>|
buzzGo(1);
if (ccActive) {
CCSpeed = CCSpeed + 4;
}
else {
ccON();
if (!ccActive && millis() < serviceTime + 10000) {
delay(1000);
serviceMode = serviceMode + 1;
for (int k = 1; k <= serviceMode; k++) {
buzzGo(1);
delay(500);
}
serviceTime = millis();
}
}
break;
case 0xFD906F: // Уменьшить скорость КК на 4 // 0xFD906F - |<<
buzzGo(1);
if (ccActive) {
CCSpeed = CCSpeed - 4;
}
if (!ccActive && millis() < serviceTime + 10000) {
delay(1000);
serviceMode = serviceMode - 1;
if (serviceMode < 1) { serviceMode = 1; }
for (int m = 1; m <= serviceMode; m++) {
buzzGo(1);
delay(500);
}
serviceTime = millis();
}
break;
case 0xFD807F: // Увеличить скорость КК на 10 // 0xFD807F - CH-
buzzGo(1);
if (ccActive) {
CCSpeed = CCSpeed + 10;
}
break;
case 0xFD40BF: // Уменьшить скорость КК на 10 // 0xFD40BF - CH+
buzzGo(1);
if (ccActive) {
CCSpeed = CCSpeed - 10;
}
break;
//////////////////////////////////////////
case 0xFDA05F: // - V- включить КК и скорость 40
buzzGo(1);
if (!ccActive) {
ccON();
}
CCSpeed = 42;
break;
case 0xFD609F: // - V+ включить КК и скорость 60
buzzGo(1);
if (!ccActive) {
ccON();
}
CCSpeed = 64;
break;
case 0xFD00FF: // - >/|| включить КК и скорость 90
buzzGo(1);
if (!ccActive) {
ccON();
}
CCSpeed = 96;
break;
case 0xFDA25D: // "call on" просто прибавить дроссель даже без КК
buzzGo(1);
setDZ(CurrDZ + 8);
ccActive = false;
if (millis() < serviceTime + 10000) {
switch (serviceMode) {
case 1:
CCSpeedDelta = CCSpeedDelta + 0.25;
indicator(CCSpeedDelta);
break;
case 2:
timePeriod = timePeriod + 100;
indicator(timePeriod);
break;
}
}
break;
case 0xFDE21D: // "call off" просто убавить дроссель даже без КК
buzzGo(1);
setDZ(CurrDZ - 8);
ccActive = false;
if (millis() < serviceTime + 10000) {
switch (serviceMode) {
case 1:
CCSpeedDelta = CCSpeedDelta - 0.25;
if (CCSpeedDelta < 0.25) { CCSpeedDelta = 0.25; }
indicator(CCSpeedDelta);
break;
case 2:
timePeriod = timePeriod - 100;
if (timePeriod < 100) { timePeriod = 100; }
indicator(timePeriod);
break;
}
}
break;
// default:
// buzzGo(9);
}
delay(50);
irrecv.resume();// Receive the next value
}
if ((ccActive || digitalRead(hallMinPin) != 0) && digitalRead(sensorBrPin) == 0) { //нажата педаль тормоза отключаем КК
ccOFF();
}
if (ccActive) {
if ((spAVG < 20) || (spAVG > 130)) {// если скорость за пределами 20..130 отключаем КК
SpeedFail = SpeedFail + 1;
if (SpeedFail > 5)
{
ccOFF();
}
}
else
{
SpeedFail = 0;
}
}
if (ccActive) {
if (spAVG < CCSpeed - CCSpeedMin) {// скорость сильно ниже заданной
digitalWrite(ledHallMinPin, HIGH);
digitalWrite(ledCCOnPin, LOW);
digitalWrite(ledHallMaxPin, LOW);
}
else
if (spAVG > CCSpeed + CCSpeedMax){// скорость сильно выше заданной
digitalWrite(ledHallMinPin, LOW);
digitalWrite(ledCCOnPin, LOW);
digitalWrite(ledHallMaxPin, HIGH);
}
else
{
digitalWrite(ledHallMinPin, LOW);
digitalWrite(ledCCOnPin, HIGH);
digitalWrite(ledHallMaxPin, LOW);
}
}
else
{
digitalWrite(ledHallMinPin, LOW);
digitalWrite(ledCCOnPin, LOW);
digitalWrite(ledHallMaxPin, LOW);
}
if (ccActive)
{// проверяем включен ли КК
if ((spAVG < CCSpeed - CCSpeedMin || spAVG > CCSpeed + CCSpeedMax) && millis() >= timeOldSpeed + timePeriod)
{// скорость за пределами нормы и настало время для след.прохода
// расчёт ускорения
SpeedUp = (spAVG - OldSpeed)/((millis() - timeOldSpeed)/1000);
// вычисляем рачётное ускорение
CalcSpeedUp = ((CCSpeed - spAVG) / (CCSpeed / CSDK));
// CalcSpeedUp = ((CCSpeed - spAVG) / (CCSpeed / CSDK)) * 1000 / (millis() - timeOldSpeed);
if (spAVG < CCSpeed - CCSpeedMin) {// скорость ниже заданной
if (SpeedUp > 0) {// если скорость в верном направлении
if (SpeedUp < CalcSpeedUp - CalcSpeedUp/5) { // если ускорение не достаточное
setDZ(CurrDZ + int((CalcSpeedUp - SpeedUp) * 15));
// setDZ(CurrDZ + int((CCSpeed - spAVG)/2 + spAVG/8));
}// *если ускорение не достаточное
else
if (SpeedUp > CalcSpeedUp + CalcSpeedUp/5 && SpeedUp > 1) { // если ускорение черезмерное
setDZ(CurrDZ - 6);
// setDZ(CurrDZ - 4 - int(abs(SpeedUp)));
}// *если ускорение черезмерное
}// *если скорость в верном направлении
else
{// если происходит снижение скорости
setDZ(CurrDZ + int(spAVG * 3));
}// *если происходит снижение скорости
}// *скорость сильно ниже заданной
else
if (spAVG > CCSpeed + CCSpeedMax){// скорость сильно выше заданной
if (spAVG > CCSpeed + 10) {// если скорость критически высока снижаем до минимума
setDZ(DZPosMin);
}// *если скорость критически высока снижаем до минимума
else
{// скорость сильно выше заданной, но не выше критической, продолжаем анализировать
if (SpeedUp < 0) {// если уже происходит снижение скорости
if ((spAVG < CCSpeed + CCSpeedMax + 1) && ((digitalRead(hallMinPin) == 0) || (SpeedUp < 1))) { // снижая скорость приближаемся к норме
setDZ(CurrDZ + int(spAVG/4));
} // *снижая скорость приближаемся к норме
}// *если уже происходит снижение скорости
else
if (SpeedUp > 0) { // если происходит увеличение скорости
setDZ(CurrDZ - 4 - int(10 * abs(SpeedUp)));
} // *если происходит увеличение скорости
}// *скорость сильно выше заданной, но не выше критической, продолжаем анализировать
}// *скорость сильно выше заданной
// запоминаем скорость как старую
OldSpeed = ReadSP_AVG();
timeOldSpeed = millis();
} // *скорость за пределами нормы и настало время для след.прохода
else // скорость в пределах нормы
if ((spAVG > CCSpeed - CCSpeedMin && spAVG < CCSpeed + CCSpeedMax) && (spAVG < OldSpeed - CCSpeedDelta || spAVG > OldSpeed + CCSpeedDelta))
{// скорость отклонилась на x км/ч
if (spAVG < OldSpeed) {// снизилась
if (spAVG > CCSpeed) {
SpeedReduction = 1;
}
else
{
SpeedReduction = int(CCSpeed - spAVG) + 1;
}
int frw;
frw = int(spAVG / 6);
// frw = int(spAVG * abs(SpeedUp) * 2.5);
if (frw < 6) frw = 6;
frw = frw * SpeedReduction;
setDZ(CurrDZ + frw);
}// *снизилась
if (spAVG > OldSpeed) {// увеличилась
if (spAVG < CCSpeed) {
SpeedIncrease = 1;
}
else
{
SpeedIncrease = int(spAVG - CCSpeed) + 1;
}
int rev;
rev = 6;
// rev = int(spAVG * abs(SpeedUp) / 4);
if (rev < 6 ) { rev = 6; }
rev = rev * SpeedIncrease;
setDZ(CurrDZ - rev);
}// *увеличилась
// delay(500);
// запоминаем скорость как старую
OldSpeed = ReadSP_AVG();
timeOldSpeed = millis();
}// *скорость отклонилась на 1 км/ч
// *скорость в пределах нормы
}// *проверяем включен ли КК и настало ли время для след.прохода
}
@mikrob24RUS
Copy link

At line 336 when reading very often, not the right codes.

@mikrob24RUS
Copy link

When the program began to increase, this error began to occur more and more often.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment