Стробоскоп

Zawertim
Offline
Зарегистрирован: 02.12.2015

Привет всем!

Я начинающий в этом деле. С паяльником на ты, а вот с программированием как то.....

Есть проблема. 

            Предыстория. 

Есть задумка на основе АРДУИНО создать стробоскоп. Обязательное условие блютз модуль- управление со смартфона. С этим все понятно. Перемигивание светодиодов ( два светодиода ) на основе скетча Blink. Требуется изменение частоты перемигивания после некоторого события ( получения сигнала с портрет блютуз). Казалось бы все просто, Но как заставить

digitaWrite(13, HIGH);

delay(100);

digitalWrite(13,LOW);

delay(100);

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

Пробовал while()- не удаётся выйти из цыкла!

Помогите, за ранее спасибо!!!

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Оно и так будет крутиться бесконечно в loop(). Чтобы менялась частота мигания, в delay() пишем не цифру в миллисекундах, а название переменной в которой будет храниться это значение. Переменную надо объявить заранее. Потом, по какому-либо событию меняем значение переменной, это значение автоматически попадет в delay()

Zawertim
Offline
Зарегистрирован: 02.12.2015

Спасибо! вчером попробую!

Zawertim
Offline
Зарегистрирован: 02.12.2015
 
 
int ledPin_1 = 12;
int ledPin_2 = 13;
 
int x ;
int y ;
int z ;
 
 
 
void setup()
    {
 
pinMode( ledPin_1,  OUTPUT);
pinMode( ledPin_2,  OUTPUT);
tone(10,500,1000);
tone(10,700,500);             
delay(100);
tone(10,500,1000);
tone(10,700,500);
delay(100);
tone(10,500,1000);
tone(10,700,500);
    }
  
 
void loop() {
 
if (Serial.available() > 0) {   
int i = Serial.read()-48;
if (i==1){ tone(10,1000,100);x==20;y==1000;z==0;}
        
if (i==2){ tone(10,1000,100);x==30;y== 500;z==0;}
        
if (i==3){ tone(10,1000,100);x==30;y== 250;z==0;}
        
if (i==4){ tone(10,1000,100);x==20;y== 30;z==1000;}
        
if (i==5){ tone(10,1000,100);x==500;y==1000;z==0;}
        
if (i==0){ tone(10,800,100);tone(10,1200,100);
            digitalWrite(12, LOW);
            digitalWrite(13, LOW);} 
         
if (i==7){ tone(10,1200,100);tone(10,800,100);
           digitalWrite(12,HIGH);
           digitalWrite(13,HIGH);}
}
 
 
digitalWrite( ledPin_1 , HIGH);
delay(x);
digitalWrite( ledPin_1 ,  LOW);
delay(y);
digitalWrite( ledPin_2 , HIGH);
delay(x);
digitalWrite( ledPin_2 ,  LOW);
delay(z);
digitalWrite( ledPin_1 , HIGH);
delay(x);
digitalWrite( ledPin_1 ,  LOW);
delay(y);
digitalWrite( ledPin_2 , HIGH);
delay(x);
digitalWrite( ledPin_2 ,  LOW); 
delay(z);
  
}
  Попробовал!
Пчалька! Не работает. Сигнал получает но ни чего не происходит! 
Araris
Araris аватар
Offline
Зарегистрирован: 09.11.2012

Оператор "==" не присвоит переменным новых значений, это оператор сравнения. Короче говоря, не x==20; , а x=20;

Zawertim
Offline
Зарегистрирован: 02.12.2015

Странно, не помогло.

Zawertim
Offline
Зарегистрирован: 02.12.2015

Просто светятся оба светодиода!

Zawertim
Offline
Зарегистрирован: 02.12.2015

Код немного изменился, но это ни чего не дало!

 
 
 
int ledPin_1 = 12;
int ledPin_2 = 13;
 
 
int x; 
int y; 
int z; 
 
 
void setup()
    {
 
pinMode( ledPin_1,  OUTPUT);
pinMode( ledPin_2,  OUTPUT);
 
    }
  
 
void loop() {
 
if (Serial.available() > 0) {   
int i = Serial.read()-48;
 
 
if (i==1){ tone(10,1000,100);x=20;y=1000;z=0;}
        
if (i==2){ tone(10,1000,100);x=30;y== 500;z=0;}
        
if (i==3){ tone(10,1000,100);x=30;y= 250;z=0;}
        
if (i==4){ tone(10,1000,100);x=20;y= 30;z=1000;}
        
if (i==5){ tone(10,1000,100);x=500;y=1000;z=0;}
        
 
 
 
 
digitalWrite( ledPin_1 , HIGH);
delay(x);
digitalWrite( ledPin_1 ,  LOW);
delay(y);
digitalWrite( ledPin_2 , HIGH);
delay(x);
digitalWrite( ledPin_2 ,  LOW);
delay(z);
digitalWrite( ledPin_1 , HIGH);
delay(x);
digitalWrite( ledPin_1 ,  LOW);
delay(y);
digitalWrite( ledPin_2 , HIGH);
delay(x);
digitalWrite( ledPin_2 ,  LOW); 
delay(z);
  
}}
 
Araris
Araris аватар
Offline
Зарегистрирован: 09.11.2012

1. Код желательно вставлять так, как описано в http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii

2. Отсутствует Serial.begin в setup()  http://arduino.ru/Serial/Begin

3. y== 500; - не исправили на y=500;

Zawertim
Offline
Зарегистрирован: 02.12.2015

Я не планируют использовать Serial порт. С какой целью есть в том необходимость? Если не затруднительно, пожалуйста!

Zawertim
Offline
Зарегистрирован: 02.12.2015

Спасибо за совет о вставке кода!

Zawertim
Offline
Зарегистрирован: 02.12.2015







int ledPin_1 = 12;
int ledPin_2 = 13;


int x; 
int y; 
int z; 


void setup()
    {

pinMode( ledPin_1,  OUTPUT);
pinMode( ledPin_2,  OUTPUT);

    }
  

void loop() {

if (Serial.available() > 0) {   
int i = Serial.read()-48;


if (i==1){ tone(10,1000,100);x=20;y=1000;z=0;}
        
if (i==2){ tone(10,1000,100);x=30;y= 500;z=0;}
        
if (i==3){ tone(10,1000,100);x=30;y= 250;z=0;}
        
if (i==4){ tone(10,1000,100);x=20;y= 30;z=1000;}
        
if (i==5){ tone(10,1000,100);x=500;y=1000;z=0;}
        




digitalWrite( ledPin_1 , HIGH);
delay(x);
digitalWrite( ledPin_1 ,  LOW);
delay(y);
digitalWrite( ledPin_2 , HIGH);
delay(x);
digitalWrite( ledPin_2 ,  LOW);
delay(z);
digitalWrite( ledPin_1 , HIGH);
delay(x);
digitalWrite( ledPin_1 ,  LOW);
delay(y);
digitalWrite( ledPin_2 , HIGH);
delay(x);
digitalWrite( ledPin_2 ,  LOW); 
delay(z);
  
}}

 

Araris
Araris аватар
Offline
Зарегистрирован: 09.11.2012

Zawertim пишет:

Я не планируют использовать Serial порт.

В этом есть некое противоречие с тем, что он уже используется в скетче :

if (Serial.available() > 0) {   
int i = Serial.read()-48;
Zawertim
Offline
Зарегистрирован: 02.12.2015

Я имею введу отображение обратных данных с ардуино- то есть односторонняя связь.

Или это необходимо,и я просто не совсем что то понимаю?

Araris
Araris аватар
Offline
Зарегистрирован: 09.11.2012

Для данного конкретного скетча необходим Serial.begin в setup().

Zawertim
Offline
Зарегистрирован: 02.12.2015

Спасибо!!!

Zawertim
Offline
Зарегистрирован: 02.12.2015

Ещё один теоретический вопросов.

Переменная i принимает какое либо значение в соответствии с полученной командой. Вопрос, значение i изменится только при получении команды, или изменится сразу после прекращения подачи команды?

Araris
Araris аватар
Offline
Зарегистрирован: 09.11.2012

Простой ответ такой : например, если в скетче прописано ii= 1; , то значение 1 будет в iii до тех пор, пока скетч его не изменит на iii = 2. Однако, не всё так просто с переменными, поэтому я бы Вам для начала посоветовал почитать хотя бы

http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-pamyat-1-chto-i-kak-ne-nado-delat

и

http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-pamyat-2-staticheskie-peremennye

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

 

Zawertim
Offline
Зарегистрирован: 02.12.2015

Спасибо!

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

Zawertim, у вас сама идеология не хорошая. Не нужно тут не tone(), ни delay(). Всё делается на таймере1.

Для запуска в терминалке (предварительно выставить скорость 9600) нужно ввести 2 числа, раздёлённых пробелом. Первое -сколько времени должен гореть светодид, второе число сколько времени должен быть потушен. В миллисекундах. Например:  30 100

Выход будет на 9 ноге ардуино.

void setup() {
Serial.begin(9600);
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0);
TCCR1B=(1<<WGM13)|(1<<CS12)|(1<<CS10);
OCR1A=1; ICR1=0;
}

void loop() {
if (Serial.available()) { 
 uint16_t x = Serial.parseInt();
 uint16_t y = Serial.parseInt();
   ICR1= (uint32_t) (x+y) *1000/128;
   OCR1A= (uint32_t) y*1000 /128;
    }
 }

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

dimax как напишет так жутко. какие-то регистры... зато коротко и красиво. хотя и на delay не длиньше было бы

Zawertim
Offline
Зарегистрирован: 02.12.2015

Не мужики, чем дальше в лес тем страшнее!

Zawertim
Offline
Зарегистрирован: 02.12.2015

После такого чувствую себя идиотом

Нельзя ли как-то прокомментировать последний скетч?

Araris
Araris аватар
Offline
Зарегистрирован: 09.11.2012

Ахахах, dimax, побойтесь Бога, топикстартер в азах нетвёрд, а Вы ему ТАКОЕ советуете... )))

Zawertim
Offline
Зарегистрирован: 02.12.2015

Прикольно!! 

Был уверен мне здесь помогут

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

Araris, да я ж не в качестве учебного пособия.. Просто как готовое решение, что б человек так не мучался :))

Zawertim, если я озвучу настройку  регистров таймера, думаете что-то будет яснее? ))  А из общего принципа - тут функция Serial() ловит из UART циферки, и с помощью них перепрограммируется таймер на отсчёт нужных отрезков времени. Но думаю это и так понятно было. Минимальная единица времени в данном скетче  -1 миллисекунда. Максимальная 4000 с чем-то, в общем для стробоскопа самое то.

Zawertim
Offline
Зарегистрирован: 02.12.2015

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

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Zawertim, если вкратце: в микроконтроллере есть аппаратные таймеры. Их нужно настраивать определённым образом, чтобы они работали в определённом режиме и тикали так, как Вам надо. Настраиваются они через регистры, как и любая переферия микроконтроллера. В эти регистры нужно записывать определенные значения. Узнать про регистры и их значения можно в даташите на конкретный микроконтроллер. На распространённых Arduino UNO, Nano, Pro Mini стоит микроконтроллер фирмы Atmel семейства AVR, а конкретно ATmega328P). То есть, это уже несколько выходит за рамки Arduino, которая расчитана в основном на новичков. Тут нужно углубляться в изучение "железной части" на более низком уровне.

Можете вот статьи почитать:

http://easyelectronics.ru/avr-uchebnyj-kurs-tajmery.html

http://www.doneathome.ru/archives/364

http://chipenable.ru/index.php/programming-avr/item/171-avr-timer-t0-ch1.html

http://chipenable.ru/index.php/programming-avr/item/187-uchebnyy-kurs-avr-taymer-schetchik-t0-rezhim-normal-ch2.html

http://chipenable.ru/index.php/programming-avr/item/191-uchebnyy-kurs-avr-taymer-schetchik-t0-rezhim-ctc-ch2.html

http://mainloop.ru/avr-atmega/avr-timer-counter.html

http://www.stepwood.com/mcucodes/2012/03/10/atmega-rezhimyi-rabotyi-taymerov-schetchikov/

http://samou4ka.net/page/tajmer-schetchik-mikrokontrollerov-avr

http://articles.greenchip.com.ua/1-0-35-0.html

http://avr-start.ru/?p=414

Zawertim
Offline
Зарегистрирован: 02.12.2015

Я понял. Будем изучать теоретическую часть. А так хотелось чего-то по быстренькому сделать. Общение наше краткое, но и почерпнул для себя нечто новое. Спасибо за помощь буду вникать!!!

Kursin
Offline
Зарегистрирован: 24.04.2017

dimax пишет:

Zawertim, у вас сама идеология не хорошая. Не нужно тут не tone(), ни delay(). Всё делается на таймере1.

Для запуска в терминалке (предварительно выставить скорость 9600) нужно ввести 2 числа, раздёлённых пробелом. Первое -сколько времени должен гореть светодид, второе число сколько времени должен быть потушен. В миллисекундах. Например:  30 100

Выход будет на 9 ноге ардуино.

void setup() {
Serial.begin(9600);
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0);
TCCR1B=(1<<WGM13)|(1<<CS12)|(1<<CS10);
OCR1A=1; ICR1=0;
}

void loop() {
if (Serial.available()) { 
 uint16_t x = Serial.parseInt();
 uint16_t y = Serial.parseInt();
   ICR1= (uint32_t) (x+y) *1000/128;
   OCR1A= (uint32_t) y*1000 /128;
    }
 }

 

Добрый день, а как переписать под MEGA 2560 или где почитать?

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

Kursin, поменять выходной пин на 11

Kursin
Offline
Зарегистрирован: 24.04.2017

ура, спасибо

Kursin
Offline
Зарегистрирован: 24.04.2017

Еще вопрос, разница заданого значения длительности имульса и измеренная осциллографом 1 мс - это нормально, если нет то в чем может быть причина. Нестабильность кварца?

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

Kursin, в данном случае нормально, т.к. следствие сильных округлений при рассчёте.

Kursin
Offline
Зарегистрирован: 24.04.2017

Спасибо за ответ. Тоесть если надо точнее то надо тип не интежер?

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

dimax пишет:

Zawertim, у вас сама идеология не хорошая. Не нужно тут не tone(), ни delay(). Всё делается на таймере1.

Для запуска в терминалке (предварительно выставить скорость 9600) нужно ввести 2 числа, раздёлённых пробелом. Первое -сколько времени должен гореть светодид, второе число сколько времени должен быть потушен. В миллисекундах. Например:  30 100

Выход будет на 9 ноге ардуино.

void setup() {
Serial.begin(9600);
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0);
TCCR1B=(1<<WGM13)|(1<<CS12)|(1<<CS10);
OCR1A=1; ICR1=0;
}

void loop() {
if (Serial.available()) { 
 uint16_t x = Serial.parseInt();
 uint16_t y = Serial.parseInt();
   ICR1= (uint32_t) (x+y) *1000/128;
   OCR1A= (uint32_t) y*1000 /128;
    }
 }

 

Dimax, а данный скетч можно настроить для генератора сигнала от 40 до 1400 Гц со скважностью 80%? или точность на каком-то диапазоне будет низкая? 

хочу использовать управление таймером вместо библиотеки PWM для решения задачи в теме http://arduino.ru/forum/programmirovanie/generator-signala-kolenvala-i-raspredvala

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

MaksVV, нет. Скетч писался под конкретную задачу. Вам нужно брать алгоритм как у меня в генераторе. Там есть возможность плавно менять частоту  и скважность, и пересчитывать сразу под неё  параметры таймера.

MaksVV
Offline
Зарегистрирован: 06.08.2015

пасиб, буду изучать.