при включении tone() ШИМ вывод отрубается (на меге)
- Войдите на сайт для отправки комментариев
Пнд, 05/12/2016 - 18:27
/* ВСЕ для Андроида*/ #define REMOTEXY_MODE__HARDSERIAL #include <RemoteXY.h> /* настройки соединения */ #define REMOTEXY_SERIAL Serial3 #define REMOTEXY_SERIAL_SPEED 9600 /* конфигурация интерфейса */ #pragma pack(push, 1) uint8_t RemoteXY_CONF[] = { 4,33,41,0,6,15,1,5,32,6 ,47,51,51,2,7,21,19,25,22,6 ,2,67,1,18,35,24,6,6,11,67 ,1,30,10,28,13,1,11,67,1,3 ,10,23,13,1,11 }; /* структура определяет все переменные вашего интерфейса управления */ struct { /* input variable */ int8_t podachaM_x; /* =-100..100 координата x положения джойстика */ int8_t podachaM_y; /* =-100..100 координата y положения джойстика */ int16_t edit_step; /* −32767.. +32767 */ /* output variable */ char Maslo[11]; /* =строка UTF8 оканчивающаяся нулем */ char ULICA[11]; /* =строка UTF8 оканчивающаяся нулем */ char KOTEL[11]; /* =строка UTF8 оканчивающаяся нулем */ /* other variable */ uint8_t connect_flag; /* =1 if wire connected, else =0 */ } RemoteXY; #pragma pack(pop) #include <EEPROM.h> #define ENCODER_DO_NOT_USE_INTERRUPTS // без прерываний. #include <Encoder.h> ///////для датчиков температуры #include <OneWire.h>// для датчиков температуры #define dallas_1 3 //пин для датчика котла (X_MIN_PIN 3) #define dallas_2 2 //пин для датчика улицы (X_MAX_PIN 2) OneWire ds_1 (dallas_1); OneWire ds_2 (dallas_2); unsigned long time=0; // тоже для измерения температуры boolean flag=0; // для измерения температуры byte data[12]; // массив float temp_1; // переменная температуры котла float temp_2; // переменная температуры улицы int raw; // переменная для арифметичесского вычитания в расчетах температуры #include <AccelStepper.h>// библиотека шаговиков AccelStepper Stepper1(1,54,55); //название движка и 1=по умолчанию (для драйвера 4488). 54=STEP . 55=DIR #define dirPin 55 //#define X_STEP_PIN54 ,#define X_DIR_PIN55, #define X_ENABLE_PIN38 #define stepPin 54 // здесь экран #include <LiquidCrystal.h> //Библиотека LCD LiquidCrystal lcd(16, 17, 23, 25, 27, 29); // переменные int dir = 1; //используется для смены направления ШД int podazh = EEPROM.read(0); // извлечь данные из памяти для шагов подачи Шд boolean alarm = true; // переменная для включения аварии int stroka = 0;// переменная номера строчек меню long previousMillis = 0; // время последнего задействования long previousMillis2 = 0; // время последнего задействования long previousMillis3 = 0; // время последнего задействования long previousMillis4 = 0; // время последнего задействования long intervalKnopok = 700; // интервал для обработки кнопок long signalSHD = 2000; // интервал после изменения переменной от энкодера ШД и до его вращения boolean state_nasos = 0; // состояние насоса типа флага что насос либо работает либо нет long nasos_Onn = 180000; // сколько минут насос работает при минусе на улице 3мин long nasos_Off = 900000; // сколько минут насос выключен при минусе на улице 15мин unsigned long new_millis_nasos = millis(); // Переменная для хранения времени //объявление входов-выходов Encoder knobEnkoder(31, 33); //кнопки энкодера int sign = 37; //бузер аварии, динамик (100 гц нормально пищит) int nasos = 10; // выход на твердотелое реле управление насосом int enter = 41; // кнопка стопа на плате int enterEnk = 35; //!!!!!!!!!!!!!!!!! кнопка на энкодере void setup() { izm_temp(); RemoteXY_Init (); Stepper1.setMaxSpeed(100000); //устанавливаем максимальную скорость вращения ротора двигателя масла(шагов/секунду) Stepper1.setAcceleration(12000); //устанавливаем ускорение (шагов/секунду^2) //Настройка пинов pinMode(enterEnk, INPUT_PULLUP); pinMode(enter, INPUT_PULLUP); pinMode(sign, OUTPUT); pinMode(nasos, OUTPUT); pinMode(dirPin, OUTPUT); pinMode(stepPin, OUTPUT); pinMode(38, OUTPUT); // 38 как выход енейбл для ШД pinMode(10, OUTPUT); // А10 как выход для включения насоса //Настройка дисплея //Установка количества столбцов и строк дисплея lcd.begin(20, 4); // Вывод приветствия при включении питания если нужно lcd.setCursor(6, 1); lcd.print("BUYANKA"); delay (2000);//Задержка приветствия lcd.clear(); } long positionLeft = -999; // позиция для энкодера в лево void loop() { RemoteXY_Handler (); // для блютуз izm_temp(); { //ОТОБРАЖЕНИЯ ТЕМПЕРАТУРЫ ВОДЫ НА ВЫХОДЕ КОТЛА lcd.setCursor(0, 0); lcd.print("KOTEL="); lcd.print(temp_1); lcd.print(" "); //отображение температуры улицы lcd.setCursor(0, 1); lcd.print("ULICA="); lcd.print(temp_2); lcd.print(" "); //подача масла lcd.setCursor(0, 2); lcd.print("PODAZHA="); lcd.print(podazh); lcd.print(" "); // сигнализация if (alarm == true ) { lcd.setCursor(0, 3); lcd.print("SIGNAL=DA "); } else if (alarm == false) { lcd.setCursor(0, 3); lcd.print("SIGNAL=NET"); } } ////////////ОБРАБОТКА БЛЮТУЗ ДЖОЙСТИКА /*if (RemoteXY.podachaM_y > 5 <10) { podazh ++ ; } */ if (RemoteXY.podachaM_y >= 10 <25) { podazh + 5 ; } if (RemoteXY.podachaM_y >= 25 <50) { podazh + 10; } if (RemoteXY.podachaM_y >= 50 <75) { podazh + 50; } if (RemoteXY.podachaM_y >= 75 <=100) { podazh + 100; } if (RemoteXY.podachaM_y > -5 < -10) { podazh --; } if (RemoteXY.podachaM_y >= -10 < -25) { podazh - 5; } if (RemoteXY.podachaM_y >= -25 < -50) { podazh - 10; } if (RemoteXY.podachaM_y >= -50 < -75) { podazh - 50; } if (RemoteXY.podachaM_y >= -75 < -100) { podazh - 100; } long newLeft; /// новая локальная переменная для энкодера /////////////////////тоже самое но для подачи шагов для вентиля newLeft = knobEnkoder.read()/4; // она равна /4 сигналам так как это приемливый делитель для моего энкодера. if (newLeft > positionLeft ){ //здесь определяется направление вращения и если строка равна 2 lcd.setCursor(8, 2); lcd.print(" "); podazh ++ ; // и увеличиваю переменную для показаний на экране positionLeft = newLeft; // запоминаю текущую позицию энкодера } if (newLeft < positionLeft){ // здесь все аналогично только уменьшаю значение на 1 lcd.setCursor(8, 2); lcd.print(" "); podazh -- ; podazh = max(podazh, 1); // ограничиваю нижний предел, не меньше 1. positionLeft = newLeft; } if (RemoteXY.edit_step > 0); { int podazh = RemoteXY.edit_step; } /////////////ПЕРЕМЕЩЕНИЕ ВЕНТИЛЯ unsigned long currentMillis = millis(); // стартовая строка для осчета времени. задержка специальная чтоб шд крутился не сразу иначе экран мигает и полная белеберда if(currentMillis - previousMillis2 > signalSHD) { // прошло время больше заданого в signalSHD previousMillis2 = currentMillis; // команда для счетчика digitalWrite(38, LOW); // отпускаю енейбле чтоб двигатель крутился ENABLE_PIN38 Stepper1.runToNewPosition(podazh * 25); // мотор движется столько сколько сейчас в переменной и * на 25 digitalWrite(38, HIGH); // подаю высокий чтоб двиг освободился ENABLE_PIN38 } itoa (podazh, RemoteXY.Maslo, 10); // вывожу показания шагов на экран андроида if (RemoteXY.edit_step > 0); { int podazh = RemoteXY.edit_step; } /////////////// команда для сигнализации if (digitalRead(enter) == LOW){ unsigned long currentMillis = millis(); if(currentMillis - previousMillis3 > intervalKnopok){ previousMillis3 = currentMillis; alarm = !alarm; } } ////////// управление насосом if (temp_1 > 40) //если температура котла больше 40гр насос включается { analogWrite(10, 180); // вкл насос } if (temp_1 < 35) //если температура котла меньше 35гр насос выключается { analogWrite(10, 0); // выкл насос } if (temp_2 < -2 && temp_1 < 1) //если температура на улице меньше -2 вкл импульсы на насос { if(millis() > new_millis_nasos) { state_nasos = !state_nasos;// инвертирую 1 на 0 и наоборот digitalWrite(10, state_nasos);//устанавливаем вывод в соответствующее состояние if(state_nasos) // если state_nasos равен 1 (больше нуля, истина,..), то { new_millis_nasos = millis() + nasos_Onn; //присваиваем переменной сумму текущего состояния счетчика и заданного времени } else { new_millis_nasos = millis() + nasos_Off; //присваиваем переменной сумму текущего состояния счетчика и заданного времени } } } //////////включаю сигнализацию если в котле больше 90 или меньше -3 /*if (temp_1 > 90 || temp_1 < -3) { unsigned long currentMillis = millis(); //запускаю отсчет if(currentMillis - previousMillis4 > 1000)// отсчитываю время 1сек { previousMillis4 = currentMillis; //сохраняю сразу время последнего включения tone (sign, 100); //пищит 100 герц analogWrite(10, 180); // вкл насос } }*/ else if (temp_1 < 87 || temp_1 > 0)// а если в котле стало ниже 87 или выше 0 то сигналка офф { noTone (sign); } } void izm_temp(){ if(!flag){ start_izm(); time=millis(); flag=1; } if(flag && (millis()-time)>750){ calc_izm(); flag=0; } } void start_izm(){ //запускаем измерение всех датчиков ds_1.reset(); ds_1.write(0xCC); ds_1.write(0x44); ds_2.reset(); ds_2.write(0xCC); ds_2.write(0x44); } void calc_izm(){ // Считываем и пересчитываем 1 датчик ds_1.reset(); ds_1.write(0xCC); ds_1.write(0xBE); // Read Scratchpad for (byte i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds_1.read (); } raw = (data[1] << 8) | data[0];//=======Пересчитываем в температуру temp_1 = (float)raw / 16.0; dtostrf(temp_1, 0, 1, RemoteXY.KOTEL); // Считываем и пересчитываем 2 датчик ds_2.reset(); ds_2.write(0xCC); ds_2.write(0xBE); // Read Scratchpad for (byte i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds_2.read (); } raw = (data[1] << 8) | data[0];//=======Пересчитываем в температуру temp_2 = (float)raw / 16.0; dtostrf(temp_2, 0, 1, RemoteXY.ULICA); }
360 строк какого-то кода и ... тишина.
Ответ уже содержится в названии темы. Две функции попали на один таймер.
Извиняюсь, вечером почему то пропадал инет..
тему создал а дописать не успел.
Да, при включении tone :
Использование функции Tone() помешает использовать ШИМ на портах вход/выхода 3 и 11 (кроме платы Arduino Mega).
У меня мега, или я не правильно понял?
:
int
sign = 37;
//бузер аварии, динамик (100 гц нормально пищит)
int
nasos = 10;
// выход на твердотелое реле управление насосом
На Меге там просто другие ноги/таймеры.
значит у меня tone использует второй таймер.
как изменить сие неудобство? посредством задействования другого таймера? перекидывать выход не есть хорошо( Там шилд
Это уж Ваша головная боль. Только связь пинов с таймерами Вы никак не измените. Так что думайте в сторону использования другого пина.
...или не используйте tone() вообще, поставьте активный буззер на любой удобный пин.
...или не используйте tone() вообще, поставьте активный буззер на любой удобный пин.
подумал об этом уже(
ну или перепаять транзистор на 8 пин для выхода. Дошло, я сначала подумал что таймера можно менять, полопатив темы понял что это железно(
разберусь.
Теперь дальше, опять втыкаюсь в постоянную и нерешаемую простой кровью смертного проблему о САМОМ сокральном вопросе со дня освоения ардуино (пауза):
" Пример с мигающим диодом не единственен. Например, поймав прерывание от нажатой кнопки, я хочу выждать, скажем, 20мс и глянуть, всё ли она ещё нажата, или то «нажатие» было просто прилетевшей помехой. Или, я хочу выждать, скажем, одну секунду, чтобы дать Wi-Fi модулю установить соединение или там дать пару секунд датчику температуры, чтобы он «согрелся», да мало ли что.
" одним словом тему от ув. ЕвгенийП
Возьмиет пример "блинк без делай".
Там что делается? "Выждать секунду, а потом выключить светодиод"
Вот и сделайте точно также, как там "выжда секунду, а потом прверить всё ли ещё нажата кнопка".
Точно как там сделайте.
вот примерно так и делаю:) подозреваю что через задницу но .. как говорится на что горазд
зацепился теперь за следующий вопрос: поиск что-то недоговаривает
Это скобки... как использовать скобки при сравнении , блин раньше как то писал а вот сейчас заморочился...(для личного понимания)
вот так?:
if ((nomerP == 1) && (relay1 == HIGH) && (UinSmooth < 21))
или
(nomerP == 2 && relay1 == HIGH && UinSmooth < 31)
и не менье интересный вопрос (для меня)
как использовать вместе && и ||
например так?
if ((nomerP == 1) && (relay1 == HIGH) && (UinSmooth < 21) || (UinSmooth2 < 21) )
ЕвгенийП
а если есть такая прозьба: запроторить меня где можно с толком и полностью разобратья с millis
А именно правильно пользоваться ими. В примитивном примере все просто и понятно, но вот как пример столкнулся с проблемой когда нужно было использовать два периода- все зависло. Потом интуитивно дошол до того что надо два previousMillis создавать и currentMillis = millis(); делать один раз а не после каждого использования. Ох как хотелось бы все в подробностях почитать за этот прием.
Сам таймер понятен тик на железном уровне но эти правила использования ... ((((
Рецепты от Лешака. Простенько и доходчиво, можете все темы почитать, не повредит.
вот так?:
if ((nomerP == 1) && (relay1 == HIGH) && (UinSmooth < 21))
или
(nomerP == 2 && relay1 == HIGH && UinSmooth < 31)
Всё равно. Но здесь очень важное правило - от скобок хуже ещё никому не становилось. Малейшее сомнение в приоритете операций - ставьте скобки и не парьтесь. По крайней мере будете уверены, что всё в порядке.
У && приоритет выше. Можете рассуждать по аналогии типа && - умножение, а || - сложение.
Но, лучше, при малейшем сомнении ставьте скобки (см. предыдущий ответ).
Ушёл к лешему, один недостаток только увидел! МАЛО ещё и ещё хочется! Как же там милиссы разжованы, это действительно полностью! Одним словом узнал много!
Спасибо ему за труд!
П.с. а приём этот сработал.
if(( vse == true) && (currentMillis - previousMillis3 > pauseOff) )
{
previousMillis3 = currentMillis;
digitalWrite(relay1, LOW);
}
Но теперь на вооружение есть что взять и от лешого. Отдельную функцию на миллисы например. Ну и конечно личные наблюдения: arduino ide1.6.12 не компилирует код с левыми функциями если тот лежит не по прямой c: дрибидень конечно но на трёх компах одно и тоже. Путь был без русских символов но копилить отказалась а вот простые кода компилит без проблем, тоисть с одним loop.
Перечитал собственный клиент - улыбнуло.
Хотел сказать с другими void
Если бы там полезные советы не были перемешаны с вредными - цены бы не было!
А это - в перлы.
Почему бы тогда уж не записывать так?
f((((( vse == true)== true)== true)== true)== true)...
Для чего эти явно лишние "== true"? Для надежности?
andriano ,в чем вредность?
Загромождает код.
Для чего эти явно лишние "== true"? Для надежности?
а вот здесь хотел спросить:
для оговорки (true у меня флаг, тоисть если bolean vse истина и задержка дошла до нужного времени то выполняю)
НО!, думаю вы не спроста спросили, а значит проверить истина или лож в bolean vse можно иным способом.
если да то как?
В операторе if между скобками находится логическое выражение. Собственно, булева переменная vse сама по себе уже есть логичемкое выражение и не следует ее ни с чем сравнивать:
Это так - общий случай. И в Вашем случае его вполне достаточно.
Но в языке Си нет специального типа для логических переменных и констант, вместо него используются целые. Так что и обычную целую переменную можно в единственном числе включать в оператор if безо всяких операторов сравнения. Если она равна нулю, это будет трактоваться как false, а если не равна - как true.