Феерично. Заинтриговался, чего тут так наобсуждали .. неужто ишо новый метод "моргать глазом" уже и без милиса, таймер и вовсе контроллера .. ан нет, всё те же и все об том же ..
Феерично. Заинтриговался, чего тут так наобсуждали .. неужто ишо новый метод "моргать глазом" уже и без милиса, таймер и вовсе контроллера .. ан нет, всё те же и все об том же ..
Звиняюсь, что вклинился..
да - усё на конденсаторах и реле. только харкор - в жопу миллис!
Smith2007, даже если бы вы запустили этот таймер недокументированными командами у вас всё равно бы ничего не получилось, т.к. он 8-битный. А вы хотели записать в его регистр 15625
Smith2007, даже если бы вы запустили этот таймер недокументированными командами у вас всё равно бы ничего не получилось, т.к. он 8-битный. А вы хотели записать в его регистр 15625
Предпочту все же документированные возможности.
Переделал на timer3. Все сразу заработало. Собрал новую схему с новой программой. Пока не приехали генератор с осцилографом - сложно чего-то отлаживать. Но я упрямый и буду дальше изучать.
Не до конца понимаю режимы WGMnx. Таймер правильно отрабатывает прерывание при WGM = 0100 (WGM32 в 1)
Переделал на timer3. Все сразу заработало. Собрал новую схему с новой программой. Пока не приехали генератор с осцилографом - сложно чего-то отлаживать. Но я упрямый и буду дальше изучать.
Не до конца понимаю режимы WGMnx. Таймер правильно отрабатывает прерывание при WGM = 0100 (WGM32 в 1)
Поможет Proteus для эмуляции МК и Codevision AVR для конфигурирования микроконтроллера. Мне связка очень помогла в настройке таймеров, в Codevision можно режимы работы таймеров мышкой выбрать, а в Proteus проверить нет ли ошибок, даже к даташиту обращаться не нужно.
Привет! Хорошие материалы делаешь. Хотел бы пообщаться. Не нашел как здесь в личку написать.. Можно в скайпе пообщаться. Есть предложение. skype batu1955
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Arduino UNO
//
////////////////////////
//
// Программа мигания светодиода /
//
unsigned int n = 0;
void setup()
{
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
void loop()
{
for (n = 0; n <= 50000; n++)
{
digitalWrite(13, HIGH);
}
for (n = 0; n <= 50000; n++)
{
digitalWrite(13, LOW);
}
}
//
// Конец /
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Вот так начинал знакомство с Ардуино несколько месяцев назад.
Возникла задача выполнять определенный фрагмент кода(конкретно выложу) в течение 10 секунд, затем переходить к остальной программе. Плата Uno на atmega 328p. Сразу отказался от millis() поскольку она уже задействована в выводе температуры и в обработке кнопок, она тормозит этот код. Понял что здесь нужно timer1. ЕвгенийП прочитал ваши этюды, спасибо вам за труд, кое что для себя почерпнул. Но для своей задачи боллее подходящее нашел в #78. Немного поковырялся, и в сериал мониторе увидел то что нужно (секунды пошли).
Вставив все это и откомпилировав обнаружил что не работает. Можете указать в чем ошибся
// это код из поста 78
word prevTCNT1;
word timeBlink = 1000;//в мсек (максимум 4194ms)
word totalTic;//15625 ==> 1000ms; 65535; ==> 4194ms максимум
void setup() {
Serial.begin(9600);
TCCR1A = 0;
TCCR1B |= (1<<CS10)|(1<<CS12); //предделитель 1024; 1 тик = 64 мкс
//TCCR1B = B101;
totalTic = 1000UL * timeBlink / 64;//сколько тиков в 1000 мсек
TCNT1 = 0;
}
void loop() {
static byte state = 0;
if(TCNT1 - prevTCNT1 >= totalTic){
prevTCNT1 = TCNT1;
state++;
Serial.println(state);
}
}
// тут идет обработка кнопок
// вывод меню
// вывод температуры каждую секунду
if (tc2 >= setTemp2) {
tone(buzzerPin, 800, 2000);
static byte state = 0;
do { // начало цикла do while
if(TCNT1 - prevTCNT1 >= totalTic){
prevTCNT1 = TCNT1;
state++;
lcd.setCursor(8, 0); // Печатаем на ЖК;
lcd.print(" "); // Режим редактирования температуры
lcd.write(4);
}
}
while( state < 10); // конец цикла do while
}
// входим в другой цикл
Конкретнее скажу так timer0 отвечает за работу delay и millis поэтому смысла не вижу его трогать, поскольку эти функции у меня задействованы, хочется на 16 битном ТС1, чего мощным ресурсам контроллера простаивать впустую если можно их задействовать на пользу
Ну простите, к ночи голова тяжелая, поправлюсь. Не millis тормозит программу, она и работает как надо, дело в том что у меня вывод температуры постоянный с интервалом в секунду, тут меня угораздило придумать еще и срабатывание по достижению заданной температуры того фрагмента кода о котором я писал в #264. Но в нем использовать millis не уместно( события выполняютя несинхронно) . Поэтому то и хочу задейтвовать посекундный счет на ТС1 и вызвать прерывание по переполнению.
Клапа, оно ведь не у меня тормозит, не считал и не хочу. Эт у нас неофит решил по хайтеку мегаточные интервалы мегабыстро мерять. Дело хорошее, для самообразования самое то.
Клапа, оно ведь не у меня тормозит, не считал и не хочу. Эт у нас неофит решил по хайтеку мегаточные интервалы мегабыстро мерять. Дело хорошее, для самообразования самое то.
та, он тут #272 пытается оправдать своё странное поведение, но я ему, почему-то, не верю.
Но в нем использовать millis не уместно( события выполняютя несинхронно) .
Во первых, что вы понимаете под словом "синхронно" при последовательном выполнении команд, ардуино "параллельно" не умеет. Насколько это "несинхронно", что вы умудряетесь его зафиксировать органами чувств данными от природы? От когда взять очумелые ручки, насытить бездумно код делаями, циклами, тонами, то потом миллис виноват в "несинхронности", а хтож еще?
Хотите таймеры изучить, это одно дело, но пытаться ими закрыть косяки в проектировании программы, поверьте, не самое умное.
Ну во первых, bwn почитайте Многозадачность на ардуино (http://robotosha.ru/arduino/multi-tasking-arduino.html), там подробно описано с примерами что независимые события могут выполняться совместно. Xumuk спасибо поправлю. #define тут лишнее(забыл убрать), насет tone скажу так, пробовал заести отдельную функцию beep, и туда поместить этот фрагмент кода, убрать delay, но понял что это необязательно, прочтите ниже
Во вторых кашу всю заварил вот от чего, свой код я разрабатываю для контроллера инфракрасной паяльной станции. В нем должны работать 1) измерение температуры с 2 термопар с показам значений на дисплее каждую секунду, 2) опрос кнопок, 3) должно идти время в формате МИН:СЕК с начала пайки.
Алгоритм такой, запустилься setup, на эране показалось "ARDUINO REWORK v0.3" на секунду( ну чуть больше), затем в loop мы переходим в MAIN_MENU и кнопками выбираем MANUAL, переходим в MENU_MANUAL, там начанается то о чем я уже писал ( вывод температуры каждую секунду и включение нагревателей)
Код до этого момента полностью рабочий и меня устраивает
#include <Wire.h> // библиотека для управления устройствами по I2C
#include <LiquidCrystal_I2C.h> // подключаем библиотеку для LCD 1602
#include "max6675.h"
#include <PID_v1.h>
#define RELAYPIN1 1 //назначаем пин "НИЖНЕГО" нагревателя
#define RELAYPIN2 0 //назначаем пин "ВЕРХНЕГО" нагревателя
#define buzzerPin 3 // назначаем пин для пьезодинамика
LiquidCrystal_I2C lcd(0x3f, 20, 4); // присваиваем имя lcd для дисплея 20х4
boolean button_state = false;
boolean button_long_state = false;
byte ButtonPress = 0;
unsigned int time_Pressed; // Переменные для работы со временем;
boolean MenuEnter;
boolean status_of_heater = 0; // флаг отображения меню
boolean thrState = 0; // флаг установки работы "ВЕРХНЕГО" нагревателя
uint8_t arrow_up[8] = {0x04, 0x0e, 0x15, 0x04, 0x04, 0x04, 0x04};
uint8_t arrow_down[8] = {0x04, 0x04, 0x04, 0x04, 0x15, 0x0e, 0x04};
uint8_t arrow_m[8] = {0x08, 0x0C, 0x0E, 0x0F, 0x0E, 0x0C, 0x08};
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
unsigned int prevTCNT1;
unsigned int timeBlink = 1000;//в мсек (максимум 4194ms)
unsigned int totalTic;//15625 ==> 1000ms; 65535; ==> 4194ms максимум
unsigned int prevmicros = 0;//переменная для хранения значений таймера
byte sek = 0; //значение секунд
byte minu = 0; //значение минут
boolean counter = false; // счетчик для полусекунд
#define PERIOD_PWM 1000UL // > 750
short kp1 = 0; short kp2 = 0;
short kd1 = 0; short kd2 = 0;
short ki1 = 0; short ki2 = 0;
boolean flag = 0; //флаг для фиксации стартовой температуры
double startTemp;
double setTemp1 = 0.0;
double setTemp2 = 0.0;
double tc1 = 0.0;
double tc2 = 0.0;
double outputPower1 = 0.0; // по умолчанию диапазон выходных значений для ШИМ устанавливается от 0 до 100
double outputPower2 = 0.0; // по умолчанию диапазон выходных значений для ШИМ устанавливается от 0 до 100
unsigned int lastTime = 0;
boolean state_top = 0;
boolean state_bottom = 0;
unsigned int prev_top, prev_bottom;
PID myPID1(&tc1, &outputPower1, &setTemp1, kp1, ki1, kd1, DIRECT);
PID myPID2(&tc2, &outputPower2, &setTemp2, kp2, ki2, kd2, DIRECT);
#define thermoDO 7
#define thermoCLK 5
#define thermoCS_b 6
#define thermoCS_t 4
MAX6675 thermocouple_b(thermoCLK, thermoCS_b, thermoDO); //термопара "НИЖНЕГО" нагревателя
MAX6675 thermocouple_t(thermoCLK, thermoCS_t, thermoDO); //термопара "ВЕРХНЕГО" нагревателя
typedef void (*LCD_menu)();
LCD_menu const menu[] =
{
setString,
timing
};
enum switchVariants { // Определения для переключателя в главном цикле;
MAIN_MENU,
MENU_MANUAL,
MENU_AUTO,
MENU_SETUP,
MENU_INFORM,
};
switchVariants switchPointer = MAIN_MENU; // С чего начнем цикл;
void setup() {
lcd.begin(); // инициализация LCD дисплея
lcd.backlight(); // включение подсветки дисплея
lcd.setCursor(1, 1);
lcd.print("ARDUINO REWORK v0.3");
lcd.createChar(1, arrow_up);
lcd.createChar(2, arrow_down);
lcd.createChar(3, arrow_m);
lcd.createChar(4, clock);
//Мелодия приветствия
tone(buzzerPin, 523);
delay(200);
tone(buzzerPin, 659);
delay(200);
tone(buzzerPin, 784);
delay(200);
tone(buzzerPin, 1046);
delay(200);
noTone(buzzerPin);
delay(1000); // wait for MAX chip to stabilize
lcd.clear();
DDRB = 0x00;
PORTB = 0b00111111;
DDRC |= 1 << RELAYPIN1;
DDRC |= 1 << RELAYPIN2;
//
TCCR1A = 0;
TCCR1B |= (1<<CS10)|(1<<CS12); //предделитель 1024; 1 тик = 64 мкс
totalTic = 1000UL * timeBlink / 64;//сколько тиков в 1000 мсек
TCNT1 = 0;
//
myPID1.SetSampleTime(1000); // Время расчета выходного сигнала
myPID1.SetOutputLimits(0, 100);
myPID1.SetMode(AUTOMATIC); // ПИД-регулятор включен
myPID2.SetSampleTime(1000); // Время расчета выходного сигнала
myPID2.SetOutputLimits(0, 100);
myPID2.SetMode(AUTOMATIC); // ПИД-регулятор включен
prev_top = millis();
prev_bottom = millis();
}
void loop() {
unsigned long Uptime = millis();
unsigned long nextRead = millis();
// тут добавить обработку кнопок настройки темп В и Н
checkForSerial(); //???
//Обработка нажатия кнопки Up
if ( !(PINB&0b00000010) && (Uptime - time_Pressed) > 200) {
time_Pressed = Uptime;
// счетчик нажатий кнопки ButtonPress
// с каждым нажатием ButtonPress++ пока ButtonPress<4
ButtonPress++;
if (ButtonPress > 3) ButtonPress = 0;
}
// Фиксируем нажатие кнопки Ok
if( !(PINB&0b00000100) && !button_state && ( Uptime - time_Pressed) > 100 ){
button_state = true;
button_long_state = false;
time_Pressed = Uptime;
}
// Фиксируем длинное нажатие кнопки Ok
if( !(PINB&0b00000100) && !button_long_state && ( Uptime - time_Pressed) > 2000 ){
status_of_heater = true;
}
// Фиксируем отпускание кнопки Ok
if( PINB&0b00000100 && button_state && ( Uptime - time_Pressed) > 50 ){
button_state = false;
time_Pressed = Uptime;
lcd.clear();
//MenuEnter = true;
ButtonClick(ButtonPress); // Вызывается функция обработки нажатия на кнопку
}
//Обработка нажатия кнопки Cansel
if (!(PINB&0b00100000) && (Uptime - time_Pressed) > 200 ) {
time_Pressed = Uptime; // Запоминаем время нажатия кнопки;
lcd.clear();
tone(buzzerPin, 1046);
delay(100);
noTone(buzzerPin);
delay(100);
tone(buzzerPin, 1046);
delay(100);
noTone(buzzerPin);
delay(100);
tone(buzzerPin, 1046);
delay(100);
noTone(buzzerPin);
delay(100);
tone(buzzerPin, 1046);
delay(100);
noTone(buzzerPin);
delay(100);
}
switch (switchPointer) // Все делаем в одном операторе и одной функции;
{
case MAIN_MENU: /***************** Главное меню ***************/
menu[0](); // включаем отображение стрелки выбора меню
lcd.setCursor(1, 0); // 1 строка
lcd.print("MANUAL"); // настройка
lcd.setCursor(1, 1); // 2 строка
lcd.print("AUTOMATIC"); // настройка
lcd.setCursor(1, 2); // 3 строка
lcd.print("SETUP"); // ручной режим
lcd.setCursor(1, 3); // 4 строка
lcd.print("INFORM"); // автоматический режим
break;
case MENU_MANUAL: /***************** Ручной режим ***************/
lcd.setCursor(0, 0); // Печатаем на ЖК;
lcd.write(2);
lcd.setCursor(1, 1); // Печатаем на ЖК;
lcd.print("TH:");
lcd.print(tc1,0);
lcd.print("\x99""C");
lcd.setCursor(11, 1); // Печатаем на ЖК;
lcd.print("TY:");
lcd.print(setTemp1,0);
lcd.print("\x99""C");
lcd.setCursor(13, 0); // Печатаем на ЖК;
lcd.print(outputPower1,0);
lcd.print("\x99""%");
lcd.setCursor(1, 3); // Печатаем на ЖК;
lcd.print("TB:");
lcd.print(tc2,0);
lcd.print("\x99""C");
lcd.setCursor(11, 3); // Печатаем на ЖК;
lcd.print("TY:");
lcd.print(setTemp2,0);
lcd.print("\x99""C");
lcd.setCursor(13, 2); // Печатаем на ЖК;
lcd.print(outputPower2,0);
lcd.print("\x99""%");
if (nextRead > lastTime + PERIOD_PWM) {
lastTime = nextRead;
tc1 = thermocouple_b.readCelsius();
tc2 = thermocouple_t.readCelsius();
myPID1.Compute(); // Расчет выходного сигнала
myPID2.Compute(); // Расчет выходного сигнала
//фиксируем стартовую температуру
if (flag == 0)
{
startTemp = tc1;
flag = 1;
}
if (!status_of_heater) {
lcd.setCursor(8, 0); // Печатаем на ЖК;
lcd.print("EDIT"); // Режим редактирования температуры
}
else {
menu[1]();
lcd.setCursor(8, 0); // Печатаем на ЖК;
lcd.print("HEAT"); // Режим редактирования температуры
// запуск работы "ВЕРХА" сразу после догрева "НИЗОМ"
if (tc1 >= setTemp1) {
outputPower1 = 0; // !!! то что ПИД не даст перегреть
thrState = 1; // флаг начала работы "ВЕРХНЕГО" нагревателя
}
// алгоритм ШИМ с частотой 5 Гц
if ((state_bottom == 0) && ((millis()-prev_bottom) >= 200 * (100 - outputPower1) / 100)) {
state_bottom = 1;
PORTC |= 1 << RELAYPIN1;
prev_bottom = millis();
}
if ((state_bottom == 1) && ((millis()-prev_bottom) >= 200 * outputPower1 / 100)) {
state_bottom = 0;
PORTC &= ~(1 << RELAYPIN1);
prev_bottom = millis();
}
//digitalWrite(RELAYPIN1, state_bottom);
// алгоритм ШИМ с частотой 5 Гц
if (thrState && (state_top == 0) && ((millis() - prev_top) >= 200 * (100 - outputPower2) / 100)) {
state_top = 1;
PORTC |= 1 << RELAYPIN2;
prev_top = millis();
}
if (thrState && (state_top == 1) && ((millis() - prev_top) >= 200 * outputPower2 / 100)) {
state_top = 0;
PORTC &= ~(1 << RELAYPIN2);
prev_top = millis();
}
//digitalWrite(RELAYPIN2, state_top);
//if (tc1 > startTemp) {
if (tc2 >= setTemp2) {
tone(buzzerPin, 800, 2000);
/* static byte state = 0;
do { // начало цикла do while
if(TCNT1 - prevTCNT1 >= totalTic){
prevTCNT1 = TCNT1;
state++;
lcd.setCursor(8, 0); // Печатаем на ЖК;
lcd.print(" "); // Режим редактирования температуры
lcd.write(4);
}
}
while( state < 10); // конец цикла do while */
}
}
}
break;
case MENU_AUTO: /***************** Автоматический режим ***************/
break;
case MENU_SETUP: /***************** Настройки ***************/
break;
case MENU_INFORM: /*********** Информация о станции *********/
break;
}
}
void setString()
{
switch (ButtonPress) {
case 1:
lcd.setCursor(0, 0);
lcd.write(32);
lcd.setCursor(0, 1);
lcd.write(62);
break;
case 2:
lcd.setCursor(0, 1);
lcd.write(32);
lcd.setCursor(0, 2);
lcd.write(62);
break;
case 3:
lcd.setCursor(0, 2);
lcd.write(32);
lcd.setCursor(0, 3);
lcd.write(62);
break;
default:
lcd.setCursor(0, 3);
lcd.write(32);
lcd.setCursor(0, 0);
lcd.write(62);
break;
}
}
void ButtonClick(byte ButtonId) {
if (ButtonId == 0) switchPointer = MENU_MANUAL; // Клик [Menu] Выход из меню
else if (ButtonId == 1) switchPointer = MENU_AUTO; //MenuCurent--; // Клик [Prev] Позицию ниже
else if (ButtonId == 2) switchPointer = MENU_SETUP; //MenuCurent++; // Клик [Next] Позиция выше
else if (ButtonId == 3) switchPointer = MENU_INFORM;//MenuItems[MenuCurent].on_click(1); // Клик [+] Увеличиваем значение выбранного параметра
}
void timing()
{
if (micros() - prevmicros > 500000)
{
prevmicros = micros(); //принимает значение каждые полсекунды
counter=!counter;
if (counter==false)
{
sek++;
lcd.setCursor(4,0);
lcd.print(":"); //выводим символ ":"между минутами и секундами
}
if(sek>59)//если переменная секунда больше 59 ...
{
sek=0;//сбрасываем ее на 0
minu++;//пишем +1 в переменную минута
}
if(minu>59)//если переменная минута больше 59 ...
{
minu=0;//сбрасываем ее на 0
}
lcd.setCursor(2,0);//выводим значение минут
if (minu>=0 && minu<10) {
lcd.print("0");
lcd.print(minu);}//количество минут
else lcd.print(minu);
lcd.setCursor(5,0);//выводим значение секунд
if (sek>=0 && sek<10) {
lcd.print("0");
lcd.print(sek);}//количество секунд
else lcd.print(sek);
}
}
void checkForSerial() {
setTemp1 = 30.0;
setTemp2 = 33.0;
myPID1.SetTunings(kp1, ki1, kd1); // Настройка ПИД-регулятора во время работы
myPID2.SetTunings(kp2, ki2, kd2); // Настройка ПИД-регулятора во время работы
/* Тут настраиваются коэффициенты ПИД*/
kp1 = 50;
ki1 = 0;
kd1 = 0;
kp2 = 50;
ki2 = 0;
kd2 = 0;
}
Насчет этого фрагмента //Обработка нажатия кнопки Cansel, оно несет такой смысл, по нажатию на эту кнопку планирую сделать короткий звуковой сигнал и переход в главное меню. Но послушайте программа не тормозит, она неправильно работает(вслушайтесь в то что опишу ниже)
if(tc2 >= setTemp2) {
312
tone(buzzerPin, 800, 2000);
313
314
/* static byte state = 0;
315
do { // начало цикла do while
316
if(TCNT1 - prevTCNT1 >= totalTic){
317
prevTCNT1 = TCNT1;
318
state++;
319
lcd.setCursor(8, 0); // Печатаем на ЖК;
320
lcd.print(" "); // Режим редактирования температуры
321
lcd.write(4);
322
}
323
}
324
while( state < 10); // конец цикла do while */
325
}
Здесь я видимо непрвильно настроил таймер 1 и этот франгмент не дает исполняться остальной чати прогаммы конкретно ветке else
else{
272
273
menu[1]();
274
275
lcd.setCursor(8, 0); // Печатаем на ЖК;
276
lcd.print("HEAT"); // Режим редактирования температуры
277
278
// запуск работы "ВЕРХА" сразу после догрева "НИЗОМ"
279
if(tc1 >= setTemp1) {
280
outputPower1 = 0; // !!! то что ПИД не даст перегреть
281
thrState = 1; // флаг начала работы "ВЕРХНЕГО" нагревателя
Не читал, но, либо Вы неправильно поняли автора той статьи (что скорее всего), либо это утверждение Вам лучше обсуждать не с bwn, а с автором и, возможно, его психиатром :))))
Пасибо, освежил. Только не обнаружил, что там противоречит сказанному мною. Если бы вы ответили на заданные мною вопросы, то поняли бы, что речь идет о "псевдопараллельности", код и действия все равно выполняются последовательно, только разрешение наших органов чувств не позволяет зафиксировать эти задержки (лампа накаливания светит равномерно, а на самом деле мигает, телевизор показывает картинку, а на самом деле рисует и т.д.), причем в приведенных мною примерах интервалы миллисов исчисляются десятками, нормальный луп выполняется за десятки-сотни микросов. Вы же умудрились на пяти кнопках и одном экране создать задержки которые начали доставлять неудобства, назначили виновным за них миллис и обратились к таймерам. "Эдак нам никаких Саратовых не хватит"("Брежнев"(с)). ИМХО.
а разве не всеравно сколько раз использовать милс в коде? вы же просто сравниваете свою переменную с милс, а сколько ваших переменных будет с ней сравнено без разницы, если ошибаюсь поправьте меня.
пока bwn изучает еретические манускрипты, хочу у тебя спросить на простом примере: как одновременно писать в пины? - что бы не по очереди записалось, а одновременно, т.е. "совместно"?
Пасибо, освежил. Только не обнаружил, что там противоречит сказанному мною. Если бы вы ответили на заданные мною вопросы, то поняли бы, что речь идет о "псевдопараллельности", код и действия все равно выполняются последовательно, только разрешение наших органов чувств не позволяет зафиксировать эти задержки (лампа накаливания светит равномерно, а на самом деле мигает, телевизор показывает картинку, а на самом деле рисует и т.д.), причем в приведенных мною примерах интервалы миллисов исчисляются десятками, нормальный луп выполняется за десятки-сотни микросов. Вы же умудрились на пяти кнопках и одном экране создать задержки которые начали доставлять неудобства, назначили виновным за них миллис и обратились к таймерам. "Эдак нам никаких Саратовых не хватит"("Брежнев"(с)). ИМХО.
bwn, признаю был не прав. Прекрасно понимаю, что процессор выполняет каждую операцию за определенное количество тактов, затем переходит к следующей. То есть чисто теоретически действия действительно выполняются последовательно, но человеку как существу медленному такты процессора не заметны.
Вы правы и по поводу моей неграмотности в работе функций времени. Я постараюсь вникнуть.
/************************************/
От остальных уже подзатыльников получил.
Поймите меня правильно ведь вы тоже раньше были новичками и тоже совершали пускай и не такие, но ошибки. Но вы учились на ошибках. Я задавая здесь вопрос хочу не готовое решение, а совет более опытного коллеги. Это мой дипломный проект, и стараюсь понять смысл каждой строчки кода, при этом частенько беру готовые фрагменты, разбираюсь в их работе и переделываю под свои нужды. Теперь же понимаю что с миллис сильно упустил
звучит как оправдание - не виноватая я, меня пидагоги заставили.
Ладно, Клапа, хотя бы адекватный(ая), не знаю как правильно и умнеть начал.
BuonanotteMasha - возьмите свой код, еще раз внимательно просмотрите. В критичных местах, сперва выполняем действия, а потом бибикаем-пиликаем. Если хотите подтверждать каждое нажатие, то ограничтесь интервалом 100мС или переписывайте без делеев. Почитайте про миллис и вторую тему "...с комфортом", мне нравится. И давайте у Евгения завязывать, ну не нужны вам таймеры. Откройте тему в "Общих" и там уже дальше.
Феерично. Заинтриговался, чего тут так наобсуждали .. неужто ишо новый метод "моргать глазом" уже и без милиса, таймер и вовсе контроллера .. ан нет, всё те же и все об том же ..
Звиняюсь, что вклинился..
Феерично. Заинтриговался, чего тут так наобсуждали .. неужто ишо новый метод "моргать глазом" уже и без милиса, таймер и вовсе контроллера .. ан нет, всё те же и все об том же ..
Звиняюсь, что вклинился..
да - усё на конденсаторах и реле. только харкор - в жопу миллис!
Новое исследование:
На вход 3 повешена кнопка.
По прерыванию int.0 (pin 3) вызываю процедуру, где происходит инкрементирование переменной.
Для проверки вывожу значение в терминал. Работает.
Теперь хочу запрограммировать Timer2 на генерацию прерывания в 1 сек.
d3,11 отключаю
При компиляции выходит ошибка, что переменная TCCR2A не определена
Как в таком случае добраться до регистров второго таймера?
Теперь хочу запрограммировать Timer2
А он у Вас есть?
Какой у Вас контроллер? Я уже как-то спрашивал, но Вы не ответили.
Arduino Leonardo
Это не котроллер - это плата.
Обычно леонардо делают на базе ATmega32u4 (хотя, если клон, то там может стоять что угодно).
Так вот, если у Вас действительно ATmega32u4 (убедитесь!), так и смотрите её даташит, а не ATmega328, который я Вам давал.
Открываем и смотрим. Таймеры №№ 0, 1, 3 и 4 есть, а таймера 2 - нету :(
так что никак Вы до него не доберётесь :(
P.S. Справедливости ради, он там есть, только недокументирован, но это не для игроков из Вашей лиги. Пока считайте, что его нет.
Спасибо за информацию.
Да, действительно в описании есть таймеры 0,1,3,4. Таймера 2 - нет.
Стандартные функции ардуино какие таймеры используют? Тотже millis?
Smith2007, даже если бы вы запустили этот таймер недокументированными командами у вас всё равно бы ничего не получилось, т.к. он 8-битный. А вы хотели записать в его регистр 15625
Smith2007, даже если бы вы запустили этот таймер недокументированными командами у вас всё равно бы ничего не получилось, т.к. он 8-битный. А вы хотели записать в его регистр 15625
Предпочту все же документированные возможности.
Переделал на timer3. Все сразу заработало. Собрал новую схему с новой программой. Пока не приехали генератор с осцилографом - сложно чего-то отлаживать. Но я упрямый и буду дальше изучать.
Не до конца понимаю режимы WGMnx. Таймер правильно отрабатывает прерывание при WGM = 0100 (WGM32 в 1)
Переделал на timer3. Все сразу заработало. Собрал новую схему с новой программой. Пока не приехали генератор с осцилографом - сложно чего-то отлаживать. Но я упрямый и буду дальше изучать.
Не до конца понимаю режимы WGMnx. Таймер правильно отрабатывает прерывание при WGM = 0100 (WGM32 в 1)
Поможет Proteus для эмуляции МК и Codevision AVR для конфигурирования микроконтроллера. Мне связка очень помогла в настройке таймеров, в Codevision можно режимы работы таймеров мышкой выбрать, а в Proteus проверить нет ли ошибок, даже к даташиту обращаться не нужно.
даже к даташиту обращаться не нужно.
Красота!
Привет! Хорошие материалы делаешь. Хотел бы пообщаться. Не нашел как здесь в личку написать.. Можно в скайпе пообщаться. Есть предложение. skype batu1955
Всем здравствуйте.
Возникла задача выполнять определенный фрагмент кода(конкретно выложу) в течение 10 секунд, затем переходить к остальной программе. Плата Uno на atmega 328p. Сразу отказался от millis() поскольку она уже задействована в выводе температуры и в обработке кнопок, она тормозит этот код. Понял что здесь нужно timer1. ЕвгенийП прочитал ваши этюды, спасибо вам за труд, кое что для себя почерпнул. Но для своей задачи боллее подходящее нашел в #78. Немного поковырялся, и в сериал мониторе увидел то что нужно (секунды пошли).
Вставив все это и откомпилировав обнаружил что не работает. Можете указать в чем ошибся
Могу конечно выложить и весь мой код полностью, но врятли у кого то будет желание туда лезть
Конкретнее скажу так timer0 отвечает за работу delay и millis поэтому смысла не вижу его трогать, поскольку эти функции у меня задействованы, хочется на 16 битном ТС1, чего мощным ресурсам контроллера простаивать впустую если можно их задействовать на пользу
Сразу отказался от millis() поскольку она уже задействована в выводе температуры и в обработке кнопок, она тормозит этот код.
Спасибо, эта фраза сделала мой день.
Сразу отказался от millis() поскольку она уже задействована в выводе температуры и в обработке кнопок, она тормозит этот код.
Спасибо, эта фраза сделала мой день.
)))), Пора возвращатся к delay().
Не вижу в этом смысла, ирония ваша понятна ( как любому новичку взявшему в руки микроконироллер)
Не вижу в этом смысла, ирония ваша понятна ( как любому новичку взявшему в руки микроконироллер)
ну, ок - чем, кроме твоих ошибочных умозаключений, подтверждено твоё утверждение, что миллис тормозит твою программу?
Не вижу в этом смысла, ирония ваша понятна ( как любому новичку взявшему в руки микроконироллер)
ну, ок - чем, кроме твоих ошибочных умозаключений, подтверждено твоё утверждение, что миллис тормозит твою программу?
Дык вызвать ее, потом вычитание, потом сравнение, потом присваивание, эт скоко тактищев то натикает.
Ну простите, к ночи голова тяжелая, поправлюсь. Не millis тормозит программу, она и работает как надо, дело в том что у меня вывод температуры постоянный с интервалом в секунду, тут меня угораздило придумать еще и срабатывание по достижению заданной температуры того фрагмента кода о котором я писал в #264. Но в нем использовать millis не уместно( события выполняютя несинхронно) . Поэтому то и хочу задейтвовать посекундный счет на ТС1 и вызвать прерывание по переполнению.
эт скоко тактищев то натикает.
скоко?
Клапа, оно ведь не у меня тормозит, не считал и не хочу. Эт у нас неофит решил по хайтеку мегаточные интервалы мегабыстро мерять. Дело хорошее, для самообразования самое то.
Клапа, оно ведь не у меня тормозит, не считал и не хочу. Эт у нас неофит решил по хайтеку мегаточные интервалы мегабыстро мерять. Дело хорошее, для самообразования самое то.
та, он тут #272 пытается оправдать своё странное поведение, но я ему, почему-то, не верю.
Но в нем использовать millis не уместно( события выполняютя несинхронно) .
Во первых, что вы понимаете под словом "синхронно" при последовательном выполнении команд, ардуино "параллельно" не умеет. Насколько это "несинхронно", что вы умудряетесь его зафиксировать органами чувств данными от природы? От когда взять очумелые ручки, насытить бездумно код делаями, циклами, тонами, то потом миллис виноват в "несинхронности", а хтож еще?
Хотите таймеры изучить, это одно дело, но пытаться ими закрыть косяки в проектировании программы, поверьте, не самое умное.
а это зачем в коде
tone временно выпильте ваш код ускорится=) и delay. как вариант создать отдельную функцию пищалки бузера, но без tone и вызывать ее когда вам надо
Здравствуйте.
Ну во первых, bwn почитайте Многозадачность на ардуино (http://robotosha.ru/arduino/multi-tasking-arduino.html), там подробно описано с примерами что независимые события могут выполняться совместно. Xumuk спасибо поправлю. #define тут лишнее(забыл убрать), насет tone скажу так, пробовал заести отдельную функцию beep, и туда поместить этот фрагмент кода, убрать delay, но понял что это необязательно, прочтите ниже
Во вторых кашу всю заварил вот от чего, свой код я разрабатываю для контроллера инфракрасной паяльной станции. В нем должны работать 1) измерение температуры с 2 термопар с показам значений на дисплее каждую секунду, 2) опрос кнопок, 3) должно идти время в формате МИН:СЕК с начала пайки.
Алгоритм такой, запустилься setup, на эране показалось "ARDUINO REWORK v0.3" на секунду( ну чуть больше), затем в loop мы переходим в MAIN_MENU и кнопками выбираем MANUAL, переходим в MENU_MANUAL, там начанается то о чем я уже писал ( вывод температуры каждую секунду и включение нагревателей)
Код до этого момента полностью рабочий и меня устраивает
Насчет этого фрагмента //Обработка нажатия кнопки Cansel, оно несет такой смысл, по нажатию на эту кнопку планирую сделать короткий звуковой сигнал и переход в главное меню. Но послушайте программа не тормозит, она неправильно работает(вслушайтесь в то что опишу ниже)
if
(tc2 >= setTemp2) {
312
tone(buzzerPin, 800, 2000);
313
314
/* static byte state = 0;
315
do { // начало цикла do while
316
if(TCNT1 - prevTCNT1 >= totalTic){
317
prevTCNT1 = TCNT1;
318
state++;
319
lcd.setCursor(8, 0); // Печатаем на ЖК;
320
lcd.print(" "); // Режим редактирования температуры
321
lcd.write(4);
322
}
323
}
324
while( state < 10); // конец цикла do while */
325
}
Здесь я видимо непрвильно настроил таймер 1 и этот франгмент не дает исполняться остальной чати прогаммы конкретно ветке else
else
{
272
273
menu[1]();
274
275
lcd.setCursor(8, 0);
// Печатаем на ЖК;
276
lcd.print(
"HEAT"
);
// Режим редактирования температуры
277
278
// запуск работы "ВЕРХА" сразу после догрева "НИЗОМ"
279
if
(tc1 >= setTemp1) {
280
outputPower1 = 0;
// !!! то что ПИД не даст перегреть
281
thrState = 1;
// флаг начала работы "ВЕРХНЕГО" нагревателя
282
}
283
284
// алгоритм ШИМ с частотой 5 Гц
285
if
((state_bottom == 0) && ((millis()-prev_bottom) >= 200 * (100 - outputPower1) / 100)) {
286
state_bottom = 1;
287
PORTC |= 1 << RELAYPIN1;
288
prev_bottom = millis();
289
}
290
if
((state_bottom == 1) && ((millis()-prev_bottom) >= 200 * outputPower1 / 100)) {
291
state_bottom = 0;
292
PORTC &= ~(1 << RELAYPIN1);
293
prev_bottom = millis();
294
}
295
//digitalWrite(RELAYPIN1, state_bottom);
296
297
// алгоритм ШИМ с частотой 5 Гц
298
if
(thrState && (state_top == 0) && ((millis() - prev_top) >= 200 * (100 - outputPower2) / 100)) {
299
state_top = 1;
300
PORTC |= 1 << RELAYPIN2;
301
prev_top = millis();
302
}
303
if
(thrState && (state_top == 1) && ((millis() - prev_top) >= 200 * outputPower2 / 100)) {
304
state_top = 0;
305
PORTC &= ~(1 << RELAYPIN2);
306
prev_top = millis();
307
}
308
//digitalWrite(RELAYPIN2, state_top);
309
310
//if (tc1 > startTemp) {
311
if
(tc2 >= setTemp2) {
312
tone(buzzerPin, 800, 2000);
313
314
/* static byte state = 0;
315
do { // начало цикла do while
316
if(TCNT1 - prevTCNT1 >= totalTic){
317
prevTCNT1 = TCNT1;
318
state++;
319
lcd.setCursor(8, 0); // Печатаем на ЖК;
320
lcd.print(" "); // Режим редактирования температуры
321
lcd.write(4);
322
}
323
}
324
while( state < 10); // конец цикла do while */
325
}
326
}
327
}
Если исполняется условие в строке 311 программа находится в простое. Повторюсь до этого момента меня все устраивало. Спасибо за понимание.
bwn почитайте Многозадачность на ардуино (http://robotosha.ru/arduino/multi-tasking-arduino.html), там подробно описано с примерами что независимые события могут выполняться совместно.
Не читал, но, либо Вы неправильно поняли автора той статьи (что скорее всего), либо это утверждение Вам лучше обсуждать не с bwn, а с автором и, возможно, его психиатром :))))
Здравствуйте.
Ну во первых, bwn почитайте Многозадачность на ардуино (http://robotosha.ru/arduino/multi-tasking-arduino.html), там подробно описано с примерами что независимые события могут выполняться совместно.
Пасибо, освежил. Только не обнаружил, что там противоречит сказанному мною. Если бы вы ответили на заданные мною вопросы, то поняли бы, что речь идет о "псевдопараллельности", код и действия все равно выполняются последовательно, только разрешение наших органов чувств не позволяет зафиксировать эти задержки (лампа накаливания светит равномерно, а на самом деле мигает, телевизор показывает картинку, а на самом деле рисует и т.д.), причем в приведенных мною примерах интервалы миллисов исчисляются десятками, нормальный луп выполняется за десятки-сотни микросов. Вы же умудрились на пяти кнопках и одном экране создать задержки которые начали доставлять неудобства, назначили виновным за них миллис и обратились к таймерам. "Эдак нам никаких Саратовых не хватит"("Брежнев"(с)). ИМХО.
а разве не всеравно сколько раз использовать милс в коде? вы же просто сравниваете свою переменную с милс, а сколько ваших переменных будет с ней сравнено без разницы, если ошибаюсь поправьте меня.
Использование функции Tone() помешает использовать ШИМ на портах вход/выхода 3 и 11
кстати она не как pulseIn() тормозит код?
Использование функции Tone() ... она не как pulseIn() тормозит код?
Рядом с tone() У него делеи стоят. Программа почти секунду стоит и только бибикает.
ну про делай это я понял=))) интересно про tone=)
Ну во первых, bwn почитайте Многозадачность на ардуино (http://robotosha.ru/arduino/multi-tasking-arduino.html), там подробно описано с примерами что независимые события могут выполняться совместно.
пока bwn изучает еретические манускрипты, хочу у тебя спросить на простом примере: как одновременно писать в пины? - что бы не по очереди записалось, а одновременно, т.е. "совместно"?
Не?
Не?
да. или
О_О
я же хочу пример многозадачности, как в манускрипте...
Думаю пора расставить "все точки над i"
Уже заметил, что стал объектом насмешек.
Пасибо, освежил. Только не обнаружил, что там противоречит сказанному мною. Если бы вы ответили на заданные мною вопросы, то поняли бы, что речь идет о "псевдопараллельности", код и действия все равно выполняются последовательно, только разрешение наших органов чувств не позволяет зафиксировать эти задержки (лампа накаливания светит равномерно, а на самом деле мигает, телевизор показывает картинку, а на самом деле рисует и т.д.), причем в приведенных мною примерах интервалы миллисов исчисляются десятками, нормальный луп выполняется за десятки-сотни микросов. Вы же умудрились на пяти кнопках и одном экране создать задержки которые начали доставлять неудобства, назначили виновным за них миллис и обратились к таймерам. "Эдак нам никаких Саратовых не хватит"("Брежнев"(с)). ИМХО.
bwn, признаю был не прав. Прекрасно понимаю, что процессор выполняет каждую операцию за определенное количество тактов, затем переходит к следующей. То есть чисто теоретически действия действительно выполняются последовательно, но человеку как существу медленному такты процессора не заметны.
Вы правы и по поводу моей неграмотности в работе функций времени. Я постараюсь вникнуть.
/************************************/
От остальных уже подзатыльников получил.
Поймите меня правильно ведь вы тоже раньше были новичками и тоже совершали пускай и не такие, но ошибки. Но вы учились на ошибках. Я задавая здесь вопрос хочу не готовое решение, а совет более опытного коллеги. Это мой дипломный проект, и стараюсь понять смысл каждой строчки кода, при этом частенько беру готовые фрагменты, разбираюсь в их работе и переделываю под свои нужды. Теперь же понимаю что с миллис сильно упустил
да. или
О_О
я же хочу пример многозадачности, как в манускрипте...
Узрей чудо - вот она истинная многозадачность (правда из другого манускрипта).
PORTD |=B00110000, правда количество задач ограничено восемью.))))
Узрей чудо - вот она истинная многозадачность (правда из другого манускрипта).
PORTD |=B00110000, правда количество задач ограничено восемью.))))
мне достаточно двух одновременно исполняемых функций - аппаратные хаки не пердлогать. О_О
Это мой дипломный проект...
звучит как оправдание - не виноватая я, меня пидагоги заставили.
Использование функции Tone() ... она не как pulseIn() тормозит код?
Рядом с tone() У него делеи стоят. Программа почти секунду стоит и только бибикает.
Существуют еще 2 варианта 1)cгенерировать необходимые частоты на 2 таймере; 2) через функцию analogWrite
Постараюсь воспользоваться обеими и также избавиться от delay
Это мой дипломный проект...
звучит как оправдание - не виноватая я, меня пидагоги заставили.
Клапауций 298, можете так считать, но для меня будет нужнее исправить допущенные ошибки и изучить основные возможности моей atmega328 -uno
но для меня будет нужнее исправить допущенные ошибки
ок. для меня нужнее выпить пива. О_О
Это мой дипломный проект...
звучит как оправдание - не виноватая я, меня пидагоги заставили.
Ладно, Клапа, хотя бы адекватный(ая), не знаю как правильно и умнеть начал.
BuonanotteMasha - возьмите свой код, еще раз внимательно просмотрите. В критичных местах, сперва выполняем действия, а потом бибикаем-пиликаем. Если хотите подтверждать каждое нажатие, то ограничтесь интервалом 100мС или переписывайте без делеев. Почитайте про миллис и вторую тему "...с комфортом", мне нравится. И давайте у Евгения завязывать, ну не нужны вам таймеры. Откройте тему в "Общих" и там уже дальше.
Мигаем без delay() с комфортом. Спасибо, нашел. Дальше продолжать обсуждения не буду
Использование функции Tone() ... она не как pulseIn() тормозит код?
Рядом с tone() У него делеи стоят. Программа почти секунду стоит и только бибикает.
Существуют еще 2 варианта 1)cгенерировать необходимые частоты на 2 таймере; 2) через функцию analogWrite
Постараюсь воспользоваться обеими и также избавиться от delay
Есть биперы с генератором, они звучат при подаче на них высокого уровня (tone не нужен). Частота у них правда одна, но бипать можно и несколько раз.
Можно и без генератора. При системном тике = полупериоду бипера, хоть 100-ю биперов можно запустить. Без тормозов.))