при включении tone() ШИМ вывод отрубается (на меге)

maxvalin
Offline
Зарегистрирован: 22.02.2016

  /* ВСЕ для Андроида*/
#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);
}


  

   

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

360 строк какого-то кода и ... тишина.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Ответ уже содержится в названии темы. Две функции попали на один таймер.

maxvalin
Offline
Зарегистрирован: 22.02.2016

 

Извиняюсь, вечером почему то пропадал инет..

тему создал а дописать не успел.

Да, при включении tone :

Использование функции Tone() помешает использовать ШИМ на портах вход/выхода 3 и 11 (кроме платы Arduino Mega).

 

У меня мега, или я не правильно понял? 

 :

int sign = 37; //бузер аварии, динамик (100 гц нормально пищит)
  int nasos = 10; // выход на твердотелое реле управление насосом

 

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

На Меге там просто другие ноги/таймеры.

На Arduino Mega 6 таймеров, причём пятый обслуживает три ноги.
 
Пины 4 и 13: timer0
Пины 11 и 12: timer1
Пины 9 и 10: timer2
Pin 2, 3 и 5: timer 3
Pin 6, 7 и 8: timer 4
Pin 46, 45 и 44: timer 5
 
Просто смотрите, чтобы tone не использовал тот таймер, который у Вас занят чем-то другим.
maxvalin
Offline
Зарегистрирован: 22.02.2016

значит у меня tone использует второй таймер.

как изменить сие неудобство? посредством задействования другого таймера? перекидывать выход не есть хорошо(  Там шилд

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Это уж Ваша головная боль. Только связь пинов с таймерами Вы никак не измените. Так что думайте в сторону использования другого пина.

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

...или не используйте tone() вообще, поставьте активный буззер на любой удобный пин.

maxvalin
Offline
Зарегистрирован: 22.02.2016

OlegK пишет:

...или не используйте tone() вообще, поставьте активный буззер на любой удобный пин.

подумал об этом уже(

ну или перепаять транзистор на 8 пин для выхода. Дошло, я сначала подумал что таймера можно менять, полопатив темы понял что это железно(   

разберусь.

Теперь дальше, опять втыкаюсь в постоянную и нерешаемую простой кровью смертного проблему  о САМОМ сокральном вопросе со дня освоения ардуино (пауза):

" Пример с мигающим диодом не единственен. Например, поймав прерывание от нажатой кнопки, я хочу выждать, скажем, 20мс и глянуть, всё ли она ещё нажата, или то «нажатие» было просто прилетевшей помехой. Или, я хочу выждать, скажем, одну секунду, чтобы дать Wi-Fi модулю установить соединение или там дать пару секунд датчику температуры, чтобы он «согрелся», да мало ли что. 

"  одним словом тему от ув. ЕвгенийП 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Возьмиет пример "блинк без делай".

Там что делается? "Выждать секунду, а потом выключить светодиод"

Вот и сделайте точно также, как там "выжда секунду, а потом прверить всё ли ещё нажата кнопка".

Точно как там сделайте.

maxvalin
Offline
Зарегистрирован: 22.02.2016

вот примерно так и делаю:) подозреваю что через задницу но .. как говорится на что горазд

  /////////// запуск флага для паузы при отключении конца зарядки второго аккумулятора  №2
  if (nomerP == 2 && relay1 == HIGH && UinSmooth < 31)// если ток заряда меньше 31 ампер- флаг вкл на отсчет времени для отключения заряда 
   {
    vse = true;
    }
  else if (nomerP == 1 && relay1 == HIGH && UinSmooth > 31)// если ток заряда опять больше 21го тогда отбой, заряжается дальше
   {
     vse = false;
    }

//////// оключение зарядки при достижения конца паузы для каждого аккумулятора
 
  if(( vse == true) && (currentMillis - previousMillis3 > pauseOff) )
  {
    previousMillis3 = currentMillis;
    digitalWrite(relay1, LOW);
    
    }

 

 

 

 

 

 

 

зацепился теперь за следующий вопрос: поиск что-то недоговаривает

Это скобки... как использовать скобки при сравнении , блин раньше как то писал а вот сейчас заморочился...(для личного понимания)

вот так?:

if ((nomerP == 1) && (relay1 == HIGH) && (UinSmooth < 21))

или 

(nomerP == 2 && relay1 == HIGH && UinSmooth < 31)

и не менье интересный вопрос (для меня)

как использовать вместе && и || 

 

например так?

if ((nomerP == 1) && (relay1 == HIGH) && (UinSmooth < 21) || (UinSmooth2 < 21) )

 

maxvalin
Offline
Зарегистрирован: 22.02.2016

ЕвгенийП 

а если есть такая прозьба:  запроторить меня где можно с толком и полностью разобратья с millis

А именно правильно пользоваться ими. В примитивном примере все просто и понятно, но вот как пример столкнулся с проблемой когда нужно было использовать два периода- все зависло. Потом интуитивно дошол до того что надо два previousMillis создавать и currentMillis = millis(); делать один раз а не после каждого использования. Ох как хотелось бы все в подробностях почитать за этот прием.

Сам таймер понятен тик на железном уровне но эти правила использования ... ((((  

bwn
Offline
Зарегистрирован: 25.08.2014

Рецепты от Лешака. Простенько и доходчиво, можете все темы почитать, не повредит.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

maxvalin пишет:

вот так?:

if ((nomerP == 1) && (relay1 == HIGH) && (UinSmooth < 21))

или 

(nomerP == 2 && relay1 == HIGH && UinSmooth < 31)

Всё равно. Но здесь очень важное правило - от скобок хуже ещё никому не становилось. Малейшее сомнение в приоритете операций - ставьте скобки и не парьтесь. По крайней мере будете уверены, что всё в порядке.

maxvalin пишет:
как использовать вместе && и ||

У && приоритет выше. Можете рассуждать по аналогии типа && - умножение, а || - сложение.

Но, лучше, при малейшем сомнении ставьте скобки (см. предыдущий ответ).

 

maxvalin
Offline
Зарегистрирован: 22.02.2016

Ушёл к лешему, один недостаток только увидел! МАЛО ещё и ещё хочется! Как же там милиссы разжованы, это действительно полностью! Одним словом узнал много!
Спасибо ему за труд!
П.с. а приём этот сработал.
if(( vse == true) && (currentMillis - previousMillis3 > pauseOff) )
{
previousMillis3 = currentMillis;
digitalWrite(relay1, LOW);
}
Но теперь на вооружение есть что взять и от лешого. Отдельную функцию на миллисы например. Ну и конечно личные наблюдения: arduino ide1.6.12 не компилирует код с левыми функциями если тот лежит не по прямой c: дрибидень конечно но на трёх компах одно и тоже. Путь был без русских символов но копилить отказалась а вот простые кода компилит без проблем, тоисть с одним loop.

maxvalin
Offline
Зарегистрирован: 22.02.2016

Перечитал собственный клиент - улыбнуло.
Хотел сказать с другими void

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

maxvalin пишет:
Ушёл к лешему, один недостаток только увидел! МАЛО ещё и ещё хочется! Как же там милиссы разжованы, это действительно полностью!

Если бы там полезные советы не были перемешаны с вредными - цены бы не было!

Цитата:
if(( vse == true)...

А это - в перлы.

Почему бы тогда уж не записывать так?

f((((( vse == true)== true)== true)== true)== true)...

Для чего эти явно лишние "== true"? Для надежности?

maxvalin
Offline
Зарегистрирован: 22.02.2016

andriano ,в чем вредность? 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Загромождает код.

maxvalin
Offline
Зарегистрирован: 22.02.2016

andriano пишет:

 

Для чего эти явно лишние "== true"? Для надежности?

а вот здесь хотел спросить:

для оговорки (true у меня флаг, тоисть если bolean vse истина и задержка дошла до нужного времени то выполняю)

НО!, думаю вы не спроста спросили, а значит проверить истина или лож в  bolean vse можно иным способом.

если да то как? 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

В операторе if между скобками находится логическое выражение. Собственно, булева переменная vse сама по себе уже есть логичемкое выражение и не следует ее ни с чем сравнивать:

if(vse)...

Это так - общий случай. И в Вашем случае его вполне достаточно.

Но в языке Си нет специального типа для логических переменных и констант, вместо него используются целые. Так что и обычную целую переменную можно в единственном числе включать в оператор if безо всяких операторов сравнения. Если она равна нулю, это будет трактоваться как false, а если не равна - как true.