Бортовой компьютер для минитрактора

Тема в разделе "Arduino & Shields", создана пользователем Промах, 10 мар 2017.

  1. Промах

    Промах Нерд

    Долго искал заводской вариант бортового компа на минитрактор с нужным мне функционалом , но ничего подобного не нашлось , посему решил может моя уно ардуина поможет ? Но после некоторого мытарства и попыток добавить 3тий тахометр в честно срисованный откуда -то скетч , наконец- то дошло то,что прерывания всего 2 , а мне вот надо больше и не то что больше ,а прям не знаю насколько больше.
    Схему сделаю без проблемм это в крови, но кодер из меня никудышный , посему возникли вопросы на которые среди интернетного мусора - можно искать ответы вечно , Товарищи дорогие , подскажите КАК ?
    В общем что имею и что нужно..........
    Есть arduino uno r3 1шт , дисплеи 16*2 i2c 1шт ,16*1 5 шт , датчики холла 3 шт , DHT11 ds18 , модуль часов реального времени на ds1302 , eeprom 24Сххх, ик пульт , кнопки всякая рассыпуха в неограниченном количестве .
    Нужно одновременно выводить на дисплей(и) данные с 3х тахометров ( обороты двигателя , ВОМ , спидометр ), время ( чч:мм) , выводить данные о моторчасах ( вычислять на основании оборотов одного из тахометров) и производить запись в энергонезависимый еепром каждые 10 минут , хорошо бы ещё вести одометр или сбрасываемый таймер ( учёт затраченного времени и километров ( соток , гектар ...)) , желательно температура и влажность с DHT11 и 1н датчик типа DS18 .
    Насколько реально это для UNO ?
     
  2. rkit

    rkit Гуру

    Вместо прерываний можно подключиться к счетчикам, что потребует почитать даташит на атмегу. В остальном проблем не вижу, если пинов хватает. Если не хватает, то берите ардуино мегу. там их с запасом будет.
     
  3. rkit

    rkit Гуру

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

    Промах Нерд

    Вот такого ответа я меньше всего хотел увидеть . Ну а если откинуть термометр и DHT11 , оставить только ;
    2 тахометра + счётчик моторчасов с отображением на дисплей и записью в память ?
     
  5. rkit

    rkit Гуру

    Мне кажется, что вы не поняли ответа. Я написал, что проблем не вижу. Чего вы торгуетесь?
     
  6. Промах

    Промах Нерд

    Дык это , плата пока одна, а я ни бум-бум в коде не знаю различий ( особенностей) использования , хотя бы понять какую Дуню заказать, всё равно в дело пойдут , ну i2c плат для дисплеев , сейчас выяснилось, что те 5 штук дисплеев 16*1 работают только с настройками 8х 2, хоть и однострочные .
    Для начала "тахо" переделан под мой индикатор,теперь бы ещё понять ,как приделать кнопки или ик пульт для настройки часов и приписать его сюда , вообще непонятно ,что дальше делать ?
    Код (C++):
    #include <Wire.h>
    #include <LiquidCrystal.h>
    volatile int val;
    volatile int val1;
    void rpm() {
      val++;
    }
    void rpm1() {
      val1++;
    }
    LiquidCrystal lcd(12, 11, 5, 4, 9, 8);
    void setup() {
      lcd.begin(8, 2);
    // Serial.begin(9600);
      attachInterrupt(0, rpm, CHANGE);
      attachInterrupt(1, rpm1, CHANGE);
      lcd.setCursor(0, 0);
      lcd.print("Taho ");
      lcd.setCursor(0, 1);
      lcd.print("2ch");
      delay (1000);
      lcd.clear();
    }
    void loop() {
      val = 0;
      val1 = 0;
      delay(500);
      lcd.setCursor(0, 0);
      lcd.print("I=");
      lcd.print((val * 60) / 2  );
      lcd.setCursor(0, 1);
      lcd.print("II=");
      lcd.print((val1 * 60) / 2 );

    }
     
  7. rkit

    rkit Гуру

    Без углубленного знания программирования не получится.
     
  8. sslobodyan

    sslobodyan Гик

    ТС, видно что вы хотите сделать интересный и достаточно сложный прибор. Разбивайте задачу на маленькие задачки и пробуйте решать. Ищите подобные вопросы в нете. Потом пишите сюда свой код и спрашивайте конкретный вопрос - вам помогут, люди здесь хорошие. Но согласен с гуру Rkitом - без знаний будет очень сложно. Но дорогу осилит ИДУЩИЙ, не ноющий "сделайте мне". Удачи в творчестве.
     
  9. rkit

    rkit Гуру

    Нельзя разделить задачу на части, если нет представления, какие там должны быть части. Сначала надо делать простые вещи, и копить запас знаний. В какой-то момент их будет достаточно, чтобы представить себе полную картину, и понять, где есть пробелы, по которым можно будет спрашивать конкретные вопросы.
     
  10. sslobodyan

    sslobodyan Гик

    Не совсем согласен. ТС уже знает что ему нужен тахометр, или несколько. Нужен вывод на экран. Нужно время. Чем не мелкие задачи? Пускай сначала разбирается с каждой такой задачкой отдельно. Понимание решения в целом придет после только после понимания этих кусочков. А как иначе учиться? Теоретически?
     
  11. rkit

    rkit Гуру

    Все эти вещи надо изначально писать, закладывая на многозадачность и отлаживаемость кода. Иначе получится очередная тема "как склеить два скетча" с портянкой из If-ов на десять страниц.
    Плюс придется выжимать из МК все ресурсы, что тоже требует дисциплины и понимания таких вещей, как оценка производительности, на что никогда не наткнуться, решая простые задачи по отдельности.
    Плюс придется читать даташит, чего тоже не будет.
    Учиться лучше всего в составе профессионально составленного курса, где сначала прошли теорию, потом закрепили на практическом примере.
     
  12. sslobodyan

    sslobodyan Гик

    Согласен и больше не спорю :) Но лично я учусь именно так - по кусочкам, разбирая работу каждого модуля контроллера отдельно, решая маленькую простую задачку . Очень сложно научиться выполнять фигуры высшего пилотажа, не научившись взлетать и садиться по прямой.
     
  13. rkit

    rkit Гуру

    Предположу, что у вас уже есть немалый опыт в программировании и электронике, а значит задача освоения чего-то нового сводится к заполнению пробелов в тех местах, где новое отличается от старого.
     
  14. Промах

    Промах Нерд

    Программировать -в этом слове у меня другие буквы , с десяток различных программаторов , более чем 20 летний опыт ремонта РЭА , немного приходилось дизассемблировать , но всё это не то , писать код не моё , несмотря на весь опыт работы с логикой и микроконтроллерами ( ремонтник , сервис-инженер) - тяжко код даётся, всё трудней запомнить команды ... но всёж попробую .... .

    Вот ещё сдвиг , с 20го раза нашёл рабочую библиотеку RTC1302 , зашил время и дату , времечко тикает и отображается , обороты двигателя показывает ( только вот проверить нечем так как забыл на работе вентиляторы кои юзал вместо датчиков холла) , спидометр по идее откалибрую правильной формулой , завтра проверю будут ли все эти данные отображатся корректно.

    Код (C++):
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    #include <DS1302.h>
    DS1302 rtc(5, 6, 7);
    //volatile int val2;
    volatile int val;
    volatile int val1;
    void rpm() {
      val++;
    }
    void rpm1() {
      val1++;
    }

    LiquidCrystal_I2C lcd(0x3f, 16, 2);
    void setup() {
      Serial.begin(9600);
      attachInterrupt(0, rpm, CHANGE); //контакт 2 на плате притяжка к +5 вольтам через 10к
      attachInterrupt(1, rpm1, CHANGE); //контакт 3 на плате притяжка к +5 вольтам через 10к
      rtc.halt(false);
      rtc.writeProtect(false);
      lcd.init();
      lcd.backlight();
      lcd.setCursor(0, 0);
      lcd.print("PC from MT");
      lcd.setCursor(0, 1);
      lcd.print("-=PROMAH=-");
      delay (1000);
      lcd.clear();
    }

    void loop() {
      val = 0; // сбрасываем счетчик и ждем.
      val1 = 0;
      //val2 = 0;
      delay(250); // так как прерывание CHANGE, срабатывает два раза
      // то и считываем каждые пол секунды.
      lcd.setCursor(0, 0);
    // lcd.print("");
      lcd.print((val * 60) );
      lcd.setCursor(4, 0);
      lcd.print("Rpm");
      lcd.setCursor(8, 0);    //текущее время
      lcd.print(rtc.getTimeStr());
      lcd.setCursor(0, 1);
      lcd.print((val1 * 60) / 60 );  //изменением значений откалибровать спидометр
      lcd.setCursor(2, 1);
      lcd.print("Km/H");
      lcd.setCursor(6, 1);
      lcd.print(" ");
      lcd.setCursor(7, 1);   // будет текущий таймер или одометр
      lcd.print("Odo-timer") ;

    }
     
  15. Tomasina

    Tomasina Сушитель лампочек Модератор

    На самом деле в Atmega328 прерывания есть на каждом пине, просто только с двумя (пины 2 и 3) новичку просто работать, остальные с заморочками и поэтому редко где упоминаются.
    Ищи про PCINT.
     
    sslobodyan нравится это.
  16. sslobodyan

    sslobodyan Гик

    Промах, забудьте о delay. Иначе не сможете обрабатывать несколько датчиков одновременно. Вместо этого запоминайте millis()+250 в переменную и потом в главном цикле отслеживайте когда она станет меньше millis(), то есть прошло 250мсек. Главный луп должен быть максимально быстрым, а вызов задач (индикация, опрос кнопок) должны происходить вот по таким "будильникам". Это если не пользовать более навороченные шедулеры и RTOS.
     
  17. Промах

    Промах Нерд

    Прерывания - непонятны, PCINT - как? ! использовать в реале, задержки пока только такие .
    Увидеть бы код с коментами на где, наверняка быстрее пойму, и по ходу это единственный для меня вариант , сплагиатить и ремейк забабахать.
    Ну вообще не понимаю чего и в какой последовательности должно идти .
    Если кто то видел нечто подобное - часы+ таймер+какойнить счётчик + кнопки
    киньте линка плиз.
     
  18. Промах

    Промах Нерд

    В общем ничё не выходит , никак не догоню как исрользовать millis и mstimer2 .
    Скажите кто нибудь цеплял RTC1302 делал на нём реально работающий проект ? Что то криво ,как то всё отображается , даже http://lesson.iarduino.ru/page/urok-17-podklyuchenie-rtc-chasy-realnogo-vremeni-s-knopkami/
    секунды бегают как попало, виснет периодически.
    Код (C++):
    // Библиотека «iarduino_RTC» разработана для RTC модуля http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html
    // Вывод времени осуществляется на LCD 1602 I2C дисплей http://iarduino.ru/shop/Displei/simvolnyy-displey-golubaya-podsvetka-lcd1602-iic-i2c.html

    // Подключаем библиотеки:
    #include <Wire.h>                            // подключаем библиотеку для работы с шиной I2C
    #include <LiquidCrystal_I2C.h>               // подключаем библиотеку для работы с LCD дисплеем
    #include <iarduino_RTC.h>                    // подключаем библиотеку для работы с RTC модулем
    LiquidCrystal_I2C lcd(0x3f,16,2);            // объявляем  переменную для работы с LCD дисплеем, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2)
    iarduino_RTC time(RTC_DS1302, 9, 10, 11);              // объявляем  переменную для работы с RTC модулем,  указывая название модуля
    // Объявляем переменные и константы:
    const uint8_t PIN_button_SET  = 2;           // указываем номер вывода arduino, к которому подключена кнопка SET
    const uint8_t PIN_button_UP   = 3;           // указываем номер вывода arduino, к которому подключена кнопка UP
    const uint8_t PIN_button_DOWN = 4;           // указываем номер вывода arduino, к которому подключена кнопка DOWN
          uint8_t VAR_mode_SHOW   = 1;           // режим вывода: 1-время 2-дата
          uint8_t VAR_mode_SET    = 0;           // режим установки времени: 0-нет 1-сек 2-мин 3-час 4-день 5-мес 6-год 7-день_недели
    void setup() {
      pinMode(PIN_button_SET,  INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
      pinMode(PIN_button_UP,   INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
      pinMode(PIN_button_DOWN, INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
      delay(300);                                // ждем 300мс
      time.begin();                              // инициируем RTC модуль
      lcd.init();                                // инициируем LCD дисплей
      lcd.backlight();                           // включаем подсветку LCD дисплея
    }
    void loop(){
      if(millis()%1000==0){                      // если прошла 1 секунда
          lcd.setCursor(0, 0);                   // устанавливаем курсор в позицию: столбец 0, строка 0
          lcd.print("iArduino.ru");              // выводим текст "iArduino.ru"
          lcd.setCursor(0, 1);                   // устанавливаем курсор в позицию: столбец 0, строка 1
        if(VAR_mode_SHOW==1){                    // если установлен режим вывода времени
          lcd.print(time.gettime("H:i:s"));      // выводим время
        }
        if(VAR_mode_SHOW==2){                    // если установлен режим вывода даты
          lcd.print(time.gettime("d-m-Y   D"));  // выводим дату
        }
        delay(1);                                // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
      }
      Func_buttons_control();                    // передаём управление кнопкам
    }
    // Функция управления кнопками:
    void Func_buttons_control(){
      uint8_t i=0;
      time.blinktime(VAR_mode_SET);                                  // мигаем устанавливаемым параметром (если VAR_mode_SET больше 0)
    //Если часы находятся в режиме установки даты/времени
      if(VAR_mode_SET){
    //  Если нажата кнопка UP
        if(digitalRead(PIN_button_UP  )){
          while(digitalRead(PIN_button_UP)){delay(50);}              // ждём пока мы не отпустим кнопку UP
          switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
          /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
          /* мин */ case 2: time.settime(-1, (time.minutes==59?0:time.minutes+1), -1, -1, -1, -1, -1); break;
          /* час */ case 3: time.settime(-1, -1, (time.Hours==23?0:time.Hours+1),     -1, -1, -1, -1); break;
          /* дни */ case 4: time.settime(-1, -1, -1, (time.day==31?1:time.day+1),         -1, -1, -1); break;
          /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==12?1:time.month+1),     -1, -1); break;
          /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==99?0:time.year+1),       -1); break;
          /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==6?0:time.weekday+1) ); break;
          }
        }
    //  Если нажата кнопка DOWN
        if(digitalRead(PIN_button_DOWN)){
          while(digitalRead(PIN_button_DOWN)){delay(50);}            // ждём пока мы её не отпустим
          switch (VAR_mode_SET){                                     // декремент (уменьшение) устанавливаемого значения
          /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
          /* мин */ case 2: time.settime(-1, (time.minutes==0?59:time.minutes-1), -1, -1, -1, -1, -1); break;
          /* час */ case 3: time.settime(-1, -1, (time.Hours==0?23:time.Hours-1),     -1, -1, -1, -1); break;
          /* дни */ case 4: time.settime(-1, -1, -1, (time.day==1?31:time.day-1),         -1, -1, -1); break;
          /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==1?12:time.month-1),     -1, -1); break;
          /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==0?99:time.year-1),       -1); break;
          /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==0?6:time.weekday-1) ); break;
          }
        }
    //  Если нажата кнопка SET
        if(digitalRead(PIN_button_SET)){
          while(digitalRead(PIN_button_SET)){                        // ждём пока мы её не отпустим
            delay(10);
            if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
          }
          if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
            VAR_mode_SET++;                                          // переходим к следующему устанавливаемому параметру
            if(VAR_mode_SHOW==1 && VAR_mode_SET>3){VAR_mode_SET=1;}  // возвращаемся к первому устанавливаемому параметру
            if(VAR_mode_SHOW==2 && VAR_mode_SET>7){VAR_mode_SET=4;}  // возвращаемся к первому устанавливаемому параметру
          }else{                                                     // если кнопка SET удерживалась дольше 2 секунд, то требуется выйти из режима установки даты/времени
            VAR_mode_SET=0;                                          // выходим из режима установки даты/времени
          }
        }
    //Если часы находятся в режиме вывода даты/времени
      }else{
    //  Если нажата кнопка SET
        if(digitalRead(PIN_button_SET)){
          while(digitalRead(PIN_button_SET)){delay(10);              // ждём пока мы её не отпустим
            if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
          }
          if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
            lcd.clear();                                             // стираем экран
            VAR_mode_SHOW=VAR_mode_SHOW==1?2:1;                      // меняем режим вывода: дата/время
          }else{                                                     // если кнопка SET удерживалась дольше 2 секунд, то требуется перейти в режим установки даты/времени
            if(VAR_mode_SHOW==1){VAR_mode_SET=1;}                    // если установлен режим вывода времени, то устанавливаемый параметр - секунды
            if(VAR_mode_SHOW==2){VAR_mode_SET=4;}                    // если установлен режим вывода даты,    то устанавливаемый параметр - день
          }
        }
      }
    }
     
  19. rkit

    rkit Гуру

    Ну делал. Нормально работает, без нареканий
     
  20. Промах

    Промах Нерд

    Если код остался , опубликуйте или линка или в личку, не могу понять что у меня с этим таймером за беда уже и подтяжки делал и индикатор и питание и кодов и библиотек разных поменяно - все равно, что- то да не так, даже в мониторе порта брешет. И главное что заменить нечем, из таймеров только НТ серии есть и ds1308 ,а на них проектов не видел.