Нужна помощь в написании программы

morskoiboy
Offline
Зарегистрирован: 07.04.2012

Друзья, накидайте простую програмку, плиз. В благодарность пошлю лучиков добра и кину 500руб на телефон.

Есть сервопривод продолжительного вращения, ардуина и кнопка. Надо, чтобы при старте привод начинал крутиться пока не нажмется кнопка, после нажатия задержка 30сек и опять крутиться в туже сторону. И так покругу. Грубо говоря нажатие кнопки должно останавливать серво на полминуты

Привод на 9 выходе, а кнопка на аналоговом входе 0

maksim
Offline
Зарегистрирован: 12.02.2012

А у сервы нулевое положение когда она не крутится какое? myservo.write(???) И у вас точно серва, а не мотор-редуктор?

leshak
Offline
Зарегистрирован: 29.09.2011

 Хм... не совсем я ясно что за "сервопривод продолжительного вращения", у него есть имя? Какая-то документация?

Если срочно - можете контакты, свои, какие-то оставить, может в скайпе это быстрее решится.

Черновик будет выглядить примерно так (в предопожении что для вращения на 9-ты пин нужно просто 5v, а кнопка подключена к земле (хотя зачем ее садить на аналоговый?).

#define BUTTON_PIN A0 // пин кнопки
#define MOTOR_PIN 9

#define PAUSE_DELAY 30000 // время паузы в миллисекундах


unsigned long waitTime=0;

void setup(){
  pinMode(MOTOR_PIN,OUTPUT); // мотор на выход
  
  pinMode(BUTTON_PIN,INPUT);  // кнопку на вход
  digitalWrite(BUTTON_PIN,HIGH);// подключили подтягивающий
}

void loop(){
  if(waitTime<millis()){ //уже пора крутить?
    digitalWrite(MOTOR_PIN,HIGH); //крутим мотор
    
    if(!digitalRead(BUTTON_PIN)){ //кнопка нажата?
      waitTime=millis()+PAUSE_DELAY; // вычисляем когда опять крутить можно будет
    }
    
  } else { // еще не пришло время крутить, waitTime>millist()
      digitalWrite(MOTOR_PIN,LOW); //отстанавливаем мотор
  }

}

 

 

maksim
Offline
Зарегистрирован: 12.02.2012

Кнопка при нажатии должна замыкать 4 пин на землю (GND).

#include <Servo.h> 

#define BUTTON 4
#define SERVO 9

#define DELAY 30 // Время задержки в СЕКУНДАХ
#define STOP 90
#define MOVE 180

Servo servo;  

boolean btn_stt = 0;     

void setup() 
{ 
  digitalWrite(BUTTON, 1);
  servo.attach(SERVO);  // attaches the servo on pin 9 to the servo object 
} 

void loop() 
{ 
  servo.write(MOVE); // Крутим серву
  
  if(!digitalRead(BUTTON) && !btn_stt){ // Если кнопка нажата то
    servo.write(STOP); // Останавливаем серву
    btn_stt = 1;
    delay(DELAY*1000); // Ждем 
  }
  
  delay(200); 
  
  if(digitalRead(BUTTON)){
    btn_stt = 0;
  }

} 

 

morskoiboy
Offline
Зарегистрирован: 07.04.2012

 Сервомотор такой http://www.electronshik.ru/card/servomotor-analogoviy-87-kg8729sm-sm-s4309r-360176-112475

 В течении часа отпишусь как работает код

morskoiboy
Offline
Зарегистрирован: 07.04.2012

Выдает 

sketch_may24b.cpp: In function 'void loop()':
sketch_may24b:21: error: 'myservo' was not declared in this scope

maksim
Offline
Зарегистрирован: 12.02.2012

Перекопируйте еще раз, я поправил.

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну раз это, все-таки серва, то мой код будет примерно проапдейтится до такого:

#include <Servo.h>

#define BUTTON_PIN A0 // пин кнопки
#define SERVO_PIN 9

#define PAUSE_DELAY 30000 // время паузы в миллисекундах

#define ROTATE 180 // угол при котором серва крутит по часовой, можно попрбовать увеличить, если нужно "быстрее крутить"
#define STOP 90 // угол при котором серва стоит, возможно чуток опытным путем подобрать нужно будет

Servo servo; 


unsigned long waitTime=0;

void setup(){
  servo.attach(SERVO_PIN); // подключаемся к серве

  
  pinMode(BUTTON_PIN,INPUT);  // кнопку на вход
  digitalWrite(BUTTON_PIN,HIGH);// подключили подтягивающий
}

void loop(){
  if(waitTime<millis()){ //уже пора крутить?
    servo.write(ROTATE); //крутим серву
    
    if(!digitalRead(BUTTON_PIN)) waitTime=millis()+PAUSE_DELAY; // если кнопка нажата вычисляем когда опять крутить можно будет
    
  } else  servo.write(STOP);  // еще не пришло время крутить, waitTime>millist(),стопорим серву

}

 

 Возможно нужно будет поигратся, подобрать константы ROTATE и STOP (условные углы при которых серва крутит и стоит, они могут отличатся от экземпляра к эксземпляру).

P.S. Кнопка на нулевом аналоговом пине, как вы описали в стартовом посте, подключена от пина к земле.

morskoiboy
Offline
Зарегистрирован: 07.04.2012

 Максим вы уже второй раз меня выручаете. Телефон у вас не менялся?

Скиньте мне свою почту или скайп, чтоб я в следующий раз напрямую 

maksim
Offline
Зарегистрирован: 12.02.2012
скайп maksimkstovo19восемь5

 

Mastino
Offline
Зарегистрирован: 03.12.2011

а я бы так сделал:

Серво на пин 9;
кнопка должна замыкать GND и RESET

#include <Servo.h>

Servo myservo;  

void setup()
{
delay(30000);  
myservo.attach(9);  
}
 
 
void loop()
{
myservo.write(20);  
}            

 

maksim
Offline
Зарегистрирован: 12.02.2012

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

Mastino
Offline
Зарегистрирован: 03.12.2011

Да я смеюсь :)

maksim
Offline
Зарегистрирован: 12.02.2012

Mastino пишет:

Да я смеюсь :)

В смысле?

Mastino
Offline
Зарегистрирован: 03.12.2011

В смысле мой sketch - это шутка:)

maksim
Offline
Зарегистрирован: 12.02.2012

Если просто кнопка и серва то нормальный скейтч, только можно myservo.write(20);  из лупа в сетап перенести.

alexx1681
Offline
Зарегистрирован: 28.05.2012

 Добрый день.Maksim вы не поможете написать небольшой скетч по техзаданию?

maksim
Offline
Зарегистрирован: 12.02.2012

Помогу.

alexx1681
Offline
Зарегистрирован: 28.05.2012

Максим,скайп включите пожалуйста. 

maksim
Offline
Зарегистрирован: 12.02.2012

Я сейчас на работе, дома буду примерно через час, вы пока в скайпе в контакты добавьтесь и техзадание подготовьте.

Anchous
Offline
Зарегистрирован: 06.06.2012

Доброе время суток. По работе возникла необходимость осуществлять контроль изменения погодных условий. А именно скорости и направления ветра, ну и температуры (как дополнение).

Для осуществления контроля температуры - датчик ds18b20, скорость ветра будет измеряться путем счета количества импульсов в единицу времени (для этого планируется использовать энкодер от шариковой мышки, подключенный к чашечному анемометру), а направление ветра будет определяться путем считывания трехзначного бинарного кода с оптопар, расположенных под флюгером, к которому будет зактреплен диск с прорезями, разделенный на 8 секторов (в соответствии с количеством сторон света и промежуточными - С, С-З, З, Ю-З, Ю, Ю-В, В, С-В). В качестве устройства отображения информации будет использован LCD дисплей 16*2. Ну и конечно часы реального времени на микросхеме DS1307. Программку накатал, используя уже имеющиеся проекты (за неё прошу сильно не бить - знаю, что много проблеммных вопросов, поэтому и выкладываю, чтоб помогли, если что не так). Вот, собственно она родимая и есть:

#include <MyLiquidCrystalRus.h> 
 #include <TimerOne.h> 
 #include <DallasTemperature.h>    
 #include <WProgram.h> 
 #include <Wire.h> 
 #include <DS1307.h> 

 MyLiquidCrystalRus lcd(12, 11, 5, 4, 3, 2); 

 DallasTemperature tempSensor; 

 int rtc[7]; 

 byte gradus[8] = 
 { 
   B00110, 
   B01001, 
   B01001, 
   B00110, 
   B00000, 
   B00000, 
   B00000, 
   B00000, 
 }; // создаем собственный символ "градус Цельсия" 

 void setup() 
 { 
    RTC.stop();                     //установка времени 
    RTC.set(DS1307_SEC,0); 
    RTC.set(DS1307_MIN,26); 
    RTC.set(DS1307_HR,15); 
    RTC.set(DS1307_DOW,6); 
    RTC.set(DS1307_DATE,15); 
    RTC.set(DS1307_MTH,06); 
    RTC.set(DS1307_YR,12); 
    RTC.start(); 
     
    pinMode(9, INPUT); 
    Timer1.initialize(); // инициализация таймера - 1 секунда по умолчанию 
    Timer1.attachInterrupt( timerIsr ); 
     
    lcd.begin(16, 2);// указываем сколько строк и символов дисплея 
 lcd.createChar(1, gradus); // присваиваем символу "градус Целься" порядковый номер 
       
 lcd.print("DS18B20 тест"); 
 tempSensor.begin(13);   // запуск датчика DS18B20 
 lcd.setCursor(12, 0); 
 lcd.print("норма");        
   delay(1000); 
   lcd.clear();    
 }  

   
   
 void loop() 
 { 
  //---------------------------- Обработка времени--------------------------- 
    RTC.get(rtc,true); // первая строка: время, дата, 

    lcd.setCursor(0,0);     //вывод на дисплей времени 
    printDigits(rtc[2],':'); 
    printDigits(rtc[1],' ');    

    printDigits(rtc[4],'/'); //вывод на дисплей даты 
    printDigits(rtc[5],'/'); 
    printDigits(rtc[6],' '); 

   
  //---------------------------- Обработка температуры------------------------ 
   lcd.setCursor(12,1); 
   int Temp=(int(tempSensor.getTemperature()*10))/10; //выводим информацию температуры на дисплей, одновременно избавляясь от сотых 
 if (Temp>0) { lcd.print("+");} 
 else {lcd.print("-");} 
    lcd.print(Temp); 
    lcd.print("\1C"); //символ "градус Цельсия" 
      delay(100); 
   
    //---------------------------- Обработка направления ветра--------------- 
 int p1[2]; 
 lcd.setCursor(0,1);  
      for(int i=0; i<2; i++) 
    {  p1[i] = digitalRead(i +6); } // опрашиваем i –ый+6 вывод 
 if (p1[]== {1, 1, 1}){ lcd.print ("С"); } //Выдает ошибку, такая работа с массивом не допустима. Как быть? 
 if (p1[]== {1, 1 ,0})  { lcd.print ("С-З"); } 
 if (p1[]== {1, 0, 0})  { lcd.print ("З"); } 
 if (p1[]== {1, 0, 1})  { lcd.print ("Ю-З"); } 
 if (p1[]== {0, 0, 1})  { lcd.print ("Ю"); } 
 if (p1[]== {0, 0, 0})  { lcd.print ("Ю-В"); } 
 if (p1[]== {0, 1, 0})  { lcd.print ("В"); } 
 if (p1[]== {0, 1, 1})  { lcd.print ("С-В"); } 
 } 

         
  void printDigits(int digits, char delimiter) 
  { 
    if(digits < 10) { 
      lcd.print('0'); 
    } 
    lcd.print(digits,DEC); 
    lcd.print(delimiter); 
  } 
   
  //---------------------------- Обработка скорости ветра--------------------------- 
  void  timerIsr() 
 {int v=0; 
 if (digitalRead(9) == HIGH) // условие на опрос 9го порта 
 { 
 int v=v+1; 
 } 
 else 
 { 
 int v=v+0; 
 } 
    lcd.setCursor(5,1);      
    lcd.print(v, ' м/с' ); //в зависимости от анемометра придется калибровать 
       
  if(v > 25)                        //  Вывод сообщения о превышении заданного значения скорости ветра 
     { 
      lcd.clear(); 
      lcd.setCursor(0, 0); 
      lcd.print("Внимание!!!");        // Предупреждение при увеличении ветра 
      delay(2000); 
      lcd.clear(); 
     
    }}

Вот собственно и все. За замечания и исправления (в частности по работе с массивом при определении направления ветра) буду очень признателен. 

maksim
Offline
Зарегистрирован: 12.02.2012

Можно считать не количество импульсов за единицу времени, а время между импульсами. Тогда информация будет более оперативной и точной, а если оперативность не нужна, то можно упростить и сделать более надежной конструкцию тахометра - использовав датчик Холла (взятый, например, из куллера от компа).

maksim
Offline
Зарегистрирован: 12.02.2012

И как то вы не в тему здесь об этом написали, можно было бы создать новую... 

Anchous
Offline
Зарегистрирован: 06.06.2012

Ну как бы тут люди с вопросом помощи написания программы обращаются, вот я и подумал, что можно сюда свои вопросы воткнуть... Хотя согласен, можно было и в отдельную тему закинуть...

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

Ну а на счет времени между импульсами - идея интересная, хотя я пока плохо себе представляю как это должно выглядеть в программе. И, честно говоря, хотелось бы обойтись без  #include <TimerOne.h>... 

Подскажите, пожалуйста, как можно решить возникшую в моей программе проблему с массивами при определении направления ветра. Весь мозг себе сломал...

Спасибо. 

 

maksim
Offline
Зарегистрирован: 12.02.2012

Использовать нужно не сам куллер (хотя можно и сам) а датчик Холла, который в нем установлен и нужно мерить не напряжерие, а сигнал с этого датчика, который дает импульс за один оборот куллера - это более простой и более надежный способ, чем ИК-энкодер от мышки. Т.е. если не хотите (или не нужно) использовать сам куллер, то разбераете его, достаете оттуда датчик Холла (или покупаете датчик Холла отдельно), затем на вращающуюся часть анемометра устанавливаете магнит, который при вращении будет проходить рядом с датчиком. Вот темка, там есть пример кода

maksim
Offline
Зарегистрирован: 12.02.2012

А по поводу определения направления не совсем понятно что у вас там такое.... каким образом оно определяется?

 

leshak
Offline
Зарегистрирован: 29.09.2011

p1 у вас объявлен как массив из двух элементов, и читаете вы тоже два элемента. А пытаетесь сравнить с массиво из трех элементов.

Так что вопрос, даже, не в том что вы сравниваете массивы неправильно, а в том что сравниваете нестравнимое. Вернее "сравнимое", но совпадений у вас не будет никогда. Два байта никогда не будут равны трем байтам :)

leshak
Offline
Зарегистрирован: 29.09.2011

 И еще, массивы-то, конечно можно сравнить, только массивы вам тут не нужны (и уж тем более массив int-ов). У вас же digitalRead возвращает 0 и 1, то есть биты. И нужно вам их 3 штуки. Для их хранения  с лихвой хватит одного байта (в него восемь бит влезть может). И память экономите (в шесть раз) и сравнивать можно обычными операторами сравнения.

byte p1=0;
  for(byte i=0;i<3;i++)p1=p1 | ( digitalRead(i+6)<< (2-i) ); // читаем 6,7,8-мую ноги и закидываем их в три младших бита.
  switch(p1){
     case B111: lcd.print ("С");break;
     case B110: lcd.print ("С-З");break;
     case B100: lcd.print ("З");break;
     case B101: lcd.print ("Ю-З");break;
     case B001: lcd.print ("Ю");break;
     case B000: lcd.print ("Ю-В");break;
     case B010: lcd.print ("В");break;
     case B011: lcd.print ("С-В");break;
     default: lcd.print("Это фигня какая-то, а не ежик"); // почему-то не совпало ни с одной кобинацией
 }

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Немного перемудрил с чтением ног. Хотя будет работать, но можно чуток попроще

 

for(byte i=0;i<3;i++)p1= (p1 <<1) |  digitalRead(i+6); // читаем 6,7,8-мую ноги и закидываем их в три младших бита.

 

Anchous
Offline
Зарегистрирован: 06.06.2012

Ё-моё, а я и не задумался, что он всего два значения считывает... leshak, огромное спасибо, что помогли разобраться с этим вопросом! Шутка с ёжиком понравилась - включу в программу эту строку! :-)

maksim, прочитал про датчик Холла и не могу понять почему это будет надежнее... Разница с оптопарой лишь в физике процесса получения  сигнала на датчик. Механику придется по-другому продумывать...  А так один в один... 

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

Anchous
Offline
Зарегистрирован: 06.06.2012

maksim, ссылочку, которую вы дали - там осуществляется счет времени между импульсами и высчитывается количество оборотов за минуту? Для проверки подключал кнопку. Выдает просто нереальные значения... Бывали и отрицательные. Скорее всего я что-то неправильно понимаю...

maksim
Offline
Зарегистрирован: 12.02.2012

Anchous пишет:
Выдает просто нереальные значения... Бывали и отрицательные. Скорее всего я что-то неправильно понимаю...

Из-за дребезга вашей кнопки получаются не реально короткие промежутки между импульсами, поэтому вы и получаете такие огромные значения, а так как переменная rpm имеет тип int, то ее максимальное значение 32767 (чего более чем достаточно для об/мин) отсюда при переполнении этой переменной у вас получаются отрицательные числа.

#define RPMpin 2 // датчик Холла
unsigned long microsold = 0;
volatile int rpm = 0;

void setup() { 
  Serial.begin(9600);
  digitalWrite(RPMpin, 1);
  //attachInterrupt(0, RPM, RISING);
  attachInterrupt(0, RPM, FALLING);
}

void loop() {
  Serial.println(rpm, DEC); // об/мин
}
void RPM (){
  rpm = (1000000.0/(micros() - microsold))*60;
  microsold = micros();
}

Проверил на кнопке с параллельно включенным ей конденсатором - все замечательно работает.
 

maksim
Offline
Зарегистрирован: 12.02.2012

Anchous пишет:
maksim, прочитал про датчик Холла и не могу понять почему это будет надежнее... Разница с оптопарой лишь в физике процесса получения  сигнала на датчик. Механику придется по-другому продумывать...  А так один в один... 

Так как анемометр стоит на открытой местности, то прийдется защищать ИК датчик от солнца и от пыли. И не нужно думать как закрепить колесо от мышки на анемометре, магнит закрепить гараздо проще.

Anchous
Offline
Зарегистрирован: 06.06.2012

И то верно... Хотя у меня в планах было сделать корпус, ведь там еще и ИК датчики от флюгера будут...

А в этих строках:

08	  //attachInterrupt(0, RPM, RISING);
09	  attachInterrupt(0, RPM, FALLING);

 в зависимости от того какую строку закомментировать будет зависеть какой уровень (лог. 1 или лог. 0) будет ожидать на pin2?

leshak
Offline
Зарегистрирован: 29.09.2011

 Почти. Эти строки указывают при каком событии должна быть вызванна функция RPM (обработчик прерывания)

  • RISING - при ИЗМЕНЕНИИ pin2 с лог.0 на лог.1
  • FALING - при изменении pin2 с лог.1 на лог.0
  • CHANGE - при любом изменении pin2 (как с 1 на 0, так и с 0 на 1)

 

Anchous
Offline
Зарегистрирован: 06.06.2012

По сути, при отключенных датчиках скорости и направления ветра он должен показывать Ю-В  0 м/с, но по факту скорость ветра скачет и показывает три значения: -10, -11, -91... Хотя просто вставил эти строки в программу.

#include <MyLiquidCrystalRus.h>
#include <DallasTemperature.h>    
#include <WProgram.h> 
#include <Wire.h> 
#include <DS1307.h>

#define RPMpin 9 // ИК датчик
unsigned long microsold = 0;
volatile int rpm = 0;

MyLiquidCrystalRus lcd(12, 11, 5, 4, 3, 2);

DallasTemperature tempSensor;

int rtc[7];

byte gradus[8] = 
 { 
   B00110, 
   B01001, 
   B01001, 
   B00110, 
   B00000, 
   B00000, 
   B00000, 
   B00000, 
 }; // создаем собственный символ "градус Цельсия"

void setup()
{
   /*RTC.stop();                             //установка времени
   RTC.set(DS1307_SEC,0); 
   RTC.set(DS1307_MIN,26); 
   RTC.set(DS1307_HR,15); 
   RTC.set(DS1307_DOW,6); 
   RTC.set(DS1307_DATE,15); 
   RTC.set(DS1307_MTH,06); 
   RTC.set(DS1307_YR,12); 
   RTC.start(); 
   */
lcd.begin(16, 2);         // указываем сколько строк и символов дисплея
lcd.createChar(1, gradus); // присваиваем символу "градус Целься" порядковый номер

tempSensor.begin(13);   // запуск датчика DS18B20 

digitalWrite(RPMpin, 1);
attachInterrupt(0, RPM, FALLING);
}  
 
  
void loop()
{
 //---------------------------- Обработка времени---------------------------
   RTC.get(rtc,true); // первая строка: время, дата, день недели

   lcd.setCursor(0,0);     //вывод на дисплей времени 
   printDigits(rtc[2],':'); 
   printDigits(rtc[1],' ');   

   printDigits(rtc[4],'/'); //вывод на дисплей даты
   printDigits(rtc[5],'/'); 
   printDigits(rtc[6],' '); 

//---------------------------- Обработка температуры---------------------------
  lcd.setCursor(11,1); 
   int Temp=(int(tempSensor.getTemperature()*10))/10; //выводим информацию температуры на дисплей, одновременно избавляясь от сотых 
 if (Temp>0) { lcd.print("+");} 
 else {lcd.print("-");} 
    lcd.print(Temp); 
    lcd.print("\1C"); //символ "градус Цельсия" 
      delay(100);
  
   //---------------------------- Обработка направления ветра ---------------------------
byte p1=0;
lcd.setCursor(0,1);  
     for(byte i=0;i<3;i++)p1= (p1 <<1) |  digitalRead(i+6); // читаем 6,7,8-мую ноги и закидываем их в три младших бита.
switch(p1){
  case B111: lcd.print ("С  ");break;
  case B110: lcd.print ("С-З");break;
  case B100: lcd.print ("З  ");break;
  case B101: lcd.print ("Ю-З");break;
  case B001: lcd.print ("Ю  ");break;
  case B000: lcd.print ("Ю-В");break;
  case B010: lcd.print ("В  ");break;
  case B011: lcd.print ("С-В");break;
}
//---------------------------- Обработка скорости ветра---------------------------
lcd.setCursor(4,1);
lcd.print(rpm, DEC); // об/мин
lcd.setCursor(7,1);     
lcd.print("м/с"); 
     
 if(rpm > 25) //  Вывод сообщения о превышении скорости ветра 
    { 
     lcd.clear(); 
     lcd.setCursor(0, 0); 
        lcd.print(" Внимание! "); // Предупреждение при увеличении ветра 
     }
}

 //---------------------------- Обработка скорости ветра---------------------------
 void RPM (){
rpm = (1000000.0/(micros() - microsold))*60;
microsold = micros();
}

//---------------------------- Обработка показания времени---------------------------
 void printDigits(int digits, char delimiter) 
 { 
   if(digits < 10) { 
     lcd.print('0'); 
   } 
   lcd.print(digits,DEC); 
   lcd.print(delimiter); 
 }

Где-то я накосячил... :-(

 

Anchous
Offline
Зарегистрирован: 06.06.2012

Вот как это выглядит на деле

 

leshak
Offline
Зарегистрирован: 29.09.2011

 >скорость ветра скачет

А зачем вам так часто обновлять показания ветра?

Просто заведите счетчик, увеличивайте его в обработчике прерывания.

А в loop, раз в секунду выводите его умноженный на 60-т (для перевода в минуту). Вот у вас и получится "усредненное за секунду". Уже не будет так прыгать. Если датчик оборотов дает дребезг, можно в этом обработчике еще запоминать время, когда был последний импульс, если прошло, например, менше 200 миллесекунд - игнорить, это дребезг.

Anchous
Offline
Зарегистрирован: 06.06.2012

 За совет, конечно, огромное спасибо, но для моего уровня знания Ардуины - это крутовато... Ладно, будем эксперементировать...

leshak
Offline
Зарегистрирован: 29.09.2011

 А нужно было не боятся, а попробовать его реализовать. Голова боится, а руки делают. Тем более что в свое изначальном скетче, хоть и кривовато, но именно по этому пути вы вначале и пошли.

Счас попробую накидать. Я правильно понял, что у вас один тик RMP-ма означает метр в секунду?

leshak
Offline
Зарегистрирован: 29.09.2011

 Вообщем примерно так:

unsigned long next_rmp_report_time=0;
volatile unsigned long rmp=0;
volatile unsigned long last_rmp_time; // время когда последний раз сработал rmp-датчик
#define RMP_DEBOUNCE 200 // если RMP будет выдать тики чаще чем это время, в миллисекундах, он будет игнорироватся. защита от дребезга. подбираете опытным путем. слишком мало - начнет ловить дребезг. слишком много - начнет пропускать реальные тики.
#define RMP_TIKS_IN_M_PER_SEC 4 // предположим что при скорости 1 м/c датчик тикает 4-ре раза за секунду. Чем выше это значение - тем "плавнее" будет показания. 
void setup(){
  attachInterrupt(0, RPM, FALLING);

}

void loop(){
  
  if(next_rmp_report_time<millis()){ // пришло время вывести скорость


    lcd.setCursor(4,1);     
    lcd.print(   (rpm/RMP_TIKS_IN_M_PER_SEC)*60 , DEC); // об/мин, умонжаем на 60-т, так как счетчик накопил данные за секунду, а репортим в минутах
    lcd.setCursor(7,1);    
    lcd.print("м/с");
    
    next_rmp_report_time=millis()+1000;// вычисляем время когда будет нужне следующий отчет, через одну секунду
    rmp=0; // обнуляем счетчик, пошли заново считать

  }
}

void RPM (){
  if(millis()-last_rmp_time>RMP_DEBOUNCE){ // прошло доcтаточно времени с предыдущего тика, это не дребезг
    rmp++; // банально увеличили счетчик
  }
  last_rmp_time=millis();// запомнили время когда последний раз тикнул RPM
  
}

 

 

Если на маленьких скоростях датчик не успевает тикнуть вообще ни разу (или слишком редко), можно репортить не раз в секунду, а раз в 10-ть сек

Anchous
Offline
Зарегистрирован: 06.06.2012

 Вот это круто! После такого подробного описания и помощи желание изучать это устройство возрастает в разы! Даже не знаю как и благодарить...

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

Anchous
Offline
Зарегистрирован: 06.06.2012

Уважаемые знатоки, у меня возник резонный вопрос следующего содержания - какую длину проводника осилит Ардуино? Другими словами на какую длину провода я смогу вытянуть свои датчики?

leshak
Offline
Зарегистрирован: 29.09.2011
Anchous
Offline
Зарегистрирован: 06.06.2012

Изучил, спасибо.

А есть ли возможность при работе с микросхемой DS1307 выводить на дисплей год не полностью, а лишь последние две цифры? 

leshak
Offline
Зарегистрирован: 29.09.2011

Действующие лица:

  • Скетч ардуины - прохожий.
  • DS1707 - его наручные часы с календарем
  • Вывод на дисплей - речь прохожего.
  • Гопник - пользователь

Гопник: эй, мужик!!! какой сейчас год?

Прохожий: (смотрит на часы), сейчас....(начинает вывод на дисплей)

-----

Вопрос: сможет ли прохожий сказать гопнику только последние цифры года? Как связанна полнота ответа прохожего с моделью часов?

Anchous
Offline
Зарегистрирован: 06.06.2012

 :-D Очень доступно и с юмором!!! :-D Спасибо за разъяснение!  

Anchous
Offline
Зарегистрирован: 06.06.2012

 По последнему вопросу нашел решение. В кусочке программы

053  //---------------------------- Обработка времени---------------------------
054  RTC.get(rtc,true); // первая строка: время, дата, день недели
055  
056  lcd.setCursor(0,0);     //вывод на дисплей времени
057  printDigits(rtc[2],':');
058  printDigits(rtc[1],' ');  
059
060  printDigits(rtc[4],'/'); //вывод на дисплей даты
061  printDigits(rtc[5],'/');
062  printDigits(rtc[6],' ');

достаточно изменить строку 62 следующим образом: 

062  printDigits(rtc[6]-2000,' ');

 и выводиться на дисплей будет не 17/06/2012, а 17/06/12