Написание скетча для arduino nano

nakhodka
Offline
Зарегистрирован: 19.11.2018

Задача состоит в следующем, необходимо написать простой скетч для Arduino Nano v3 и ATtiny85 
Понимаю, что для знающих людей данная задача не является сколь либо сложной, но сам пока не могу реализовать, ввиду не достаточного опыта программирования ардуин.

Исходные данные:
Имеется, датчик скорости и направления TLE4669 ;
Эл. двигатель с 10-ю магнитами на валу. Диаметр круга на которм по краю, размещены магниты 80мм;
Контроллер на Arduino Nano v3 и ATtiny85.

Задача: написать скетч для опледеления наличия (не скорости!) вращения и направления вращения вала.

Скорость вращения вала от 0 до 1000 об/м

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

У датчиков TLE4669, направление вращения указывается изменением уровня сигнала на выходе, например, вправо логическая 1 влево  0, скорость на другом выходе, так же логическом. По ссылке выше можно узнать про датчик более подробно.

 

 

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А чо, на лекции не ходил?

nakhodka
Offline
Зарегистрирован: 19.11.2018

Когда я учился этого было только в фантастике и соответсвенно нам это не преподавали. Это для меня новое и вот сейчас изучаю самостоятельно.

В свое время собирал на логике, но не устраивает сейчас, хочется по компактнее ну и в ногу со временем.

sadman41
Offline
Зарегистрирован: 19.10.2016

Интересная штука. Я бы поковырял ея, если не к спеху.

nakhodka
Offline
Зарегистрирован: 19.11.2018

Да, действительно интересная. Но времени у меня мало. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

а задача уж больно смахивает на академическую. 

nakhodka
Offline
Зарегистрирован: 19.11.2018

DetSimen пишет:

а задача уж больно смахивает на академическую. 

чем именно?

sadman41
Offline
Зарегистрирован: 19.10.2016

Мало - это сколько? Пишите подробности на wrk.sadman@gmial.com , если желаете.

P.S. Это не вы ли с MRTG у меня были?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

nakhodka пишет:

Задача состоит в следующем, необходимо написать простой скетч для Arduino Nano v3 и ATtiny85 
Понимаю, что для знающих людей данная задача не является сколь либо сложной, но сам пока не могу реализовать, ввиду не достаточного опыта программирования ардуин.

А как вы это понимаете, если сами не имете "достаточного опыта" ?

Почему два контроллера ?

Если готовы заплатить больше 10000 рублей и находитесь в Москве то brokly(at)mail.ru

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

89995897024 watsapp, viber

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

1. размести датчик около своего вала, подключи питание 5В.

2. возьми у друзей цифровой осцилограф и сними осцилограммы с Q1 и Q2.

3. Выложи их сюда. Желательно на разных скоростях и направлениях вращения.

4. Не скажу за других, но по мне, после этого программа займет 5-10 строчек. Возможно потребуется какая-то обвязка для датчика - посмотрев картинки - я смогу сказать какая.

------

5. Ты должен понимать несовместность условия задачи: "от 0 до..." значит, что нужно определить минимальную скорость вращения. У тебя 10 магнитов на валу - значит 10 импульсов на оборот. Сколько времени ждать импульса? Ровно столько, после остановки вала, будет продолжать гореть твоя лампочка.

------------------------

В предположении "без обвязки" (схема включения из ДШ) и импульс четкий и читаемый на каждый магнит (вот это всё и нужно проверить осцилографом) - код может быть самым простым:

/*
 * Предполагаем плату Уно или Нано
 * для ат85 другие пины int0 - PB2, остальные pb0,1,3
 */
const byte inQ2 =  2; //speed INT0
const byte inQ1 =  4; // dir
const byte outD1 = 5; //на выходах активный 0
const byte outD2 = 6;
const uint32_t timeOut = 500; //0.5 сек ждем импульса

uint32_t lastChange = 0;
void checkRotation(void);

void setup() {
 pinMode (outD1,OUTPUT);
 digitalWrite (outD1,HIGH);
 pinMode (outD2,OUTPUT);
 digitalWrite (outD2,HIGH);

 attachInterrupt(0,checkRotation,CHANGE);
}

void loop() {
 if (millis() - lastChange < timeOut) {
  byte d = digitalRead(inQ1);
  // или наоборот, зависит от установки датчика и реле
  digitalWrite (outD1, d);  
  digitalWrite (outD2,!d);  
 }
 else {
  digitalWrite (outD1,HIGH);
  digitalWrite (outD2,HIGH);
 }
}

void checkRotation(void) {
  lastChange = millis();
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

только чтение lastChange в лупе атомизировать неплохо было бы. 

strarbit
strarbit аватар
Offline
Зарегистрирован: 12.06.2016

from 10000 рублей  webserpantin  gmail.com 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

sadman41 пишет:

только чтение lastChange в лупе атомизировать неплохо было бы. 

эт точно.

nakhodka
Offline
Зарегистрирован: 19.11.2018

sadman41 пишет:

Мало - это сколько? Пишите подробности на wrk.sadman@gmial.com , если желаете.

P.S. Это не вы ли с MRTG у меня были?

да, это был я, всё работает и по сей день, без нареканий! Я только немного доработал внешний вид, под себя, в остальном всё как в исходнике. Правда пришлось закрыть свободный доступ, наружу, задолбали злобные "хакеры" хохляцкие и китаёзы. Всё наровили пароли подобрать. 

Завтра отпишусь, сегодня пятница и малость устал... тяжелый день, затем огород, теплица ну и пол литры сэма в догонку.... да и ночь у нас уже поздняя.

nakhodka
Offline
Зарегистрирован: 19.11.2018

Спасибо всем кто откликнулся! Особенно wdrakula и sadman41

nakhodka
Offline
Зарегистрирован: 19.11.2018

sadman41 пишет:

Мало - это сколько? Пишите подробности на wrk.sadman@gmial.com , если желаете.

P.S. Это не вы ли с MRTG у меня были?

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

nakhodka
Offline
Зарегистрирован: 19.11.2018

brokly пишет:

nakhodka пишет:

Задача состоит в следующем, необходимо написать простой скетч для Arduino Nano v3 и ATtiny85 
Понимаю, что для знающих людей данная задача не является сколь либо сложной, но сам пока не могу реализовать, ввиду не достаточного опыта программирования ардуин.

А как вы это понимаете, если сами не имете "достаточного опыта" ?

Почему два контроллера ?

  понимание есть, опыта не хватает.

Цитата:
Если готовы заплатить больше 10000 рублей и находитесь в Москве то brokly(at)mail.ru

я не в Москве, я в Находке, а это 10000 км от Москвы. И за 10К, я лучше оставлю все как есть.

Gas311
Gas311 аватар
Offline
Зарегистрирован: 06.12.2018

А за 1000 р согласен?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Gas311 пишет:

А за 1000 р согласен?

и детальки тебе выслать, безвозвратно :)

strarbit
strarbit аватар
Offline
Зарегистрирован: 12.06.2016

Быстро скажу, TLE чип персонально имеет определение направление вращение на пин Q1,
стого достаточно просто установка  чип триггер логика.

karamzin01
Offline
Зарегистрирован: 08.03.2018

Р е а л и з у е м о - maslachenko767@mail.ru, пишите, пообщаемся

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

только чтение lastChange в лупе атомизировать неплохо было бы. 

поясни пожалуйста

sadman41
Offline
Зарегистрирован: 19.10.2016

ua6em пишет:

sadman41 пишет:

только чтение lastChange в лупе атомизировать неплохо было бы. 

поясни пожалуйста

Поясняю: изменение четырёхбайтовой переменной идёт в прерывании, которое может произойти во время чтения этой же переменной в loop(). В результате - до возникновения прерывания считается часть одного значения, а после возврата из обработчика дочитается остаток, но уже другого значения. Проще говоря: байт от  значения 15 и три байта от 16. Ну, или с иным раскладом. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

ua6em пишет:

sadman41 пишет:

только чтение lastChange в лупе атомизировать неплохо было бы. 

поясни пожалуйста

Поясняю: изменение четырёхбайтовой переменной идёт в прерывании, которое может произойти во время чтения этой же переменной в loop(). В результате - до возникновения прерывания считается часть одного значения, а после возврата из обработчика дочитается остаток, но уже другого значения. Проще говоря: байт от  значения 15 и три байта от 16. Ну, или с иным раскладом. 

и как это побороть?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

ua6em пишет:

и как это побороть?

https://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html - ну или просто noInterrupts(), читаем в локальную переменную из переменной, которая изменяется в прерывании, interrupts(). Ниже - иллюстрация:

volatile uint32_t isrVar = 0;

void isr()
{
	isrVar++;
}

void setup()
{
	Serial.begin(57600);
	attachInterrupt(digitalPinToInterrupt(2),isr,RISING);
}

void loop()
{
	noInterrupts();
	uint32_t localVar = isrVar;
	interrupts();
	
	Serial.print(F("isrVar="));
	Serial.println(localVar);
	
}

 

promavto
Offline
Зарегистрирован: 30.04.2013

ua6em пишет:

и как это побороть?

Может лучше применить небольшой кольцевой буфер, как с работой АЦП по прерыванию и флагом готовности. Все таки запрещать прерывания, мне кажется не очень хорошо.

sadman41
Offline
Зарегистрирован: 19.10.2016

Бессмысленное усложнение для данной задачи, как по мне. Операции с буфером в блокирующем обработчике могут даже дольше идти, чем атомарный перенос четырех байт. 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А чем усложнение чревато ? Ресурсы есть. К тому же если эту задачу расширить до функций энкодера, то самое оно.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

sadman41 пишет:

Бессмысленное усложнение для данной задачи, как по мне. Операции с буфером в блокирующем обработчике могут даже дольше идти, чем атомарный перенос четырех байт. 

Для атомарного чтения именно ПРАВИЛЬНО - блокировать прерывания, в loop() это можно делать просто через cli-sti.

Если прерывание по фронту-спаду, то факт события прерывания будет запомнен и прерывание исполнится, после снятия запрета. Так мы не потеряем событие. Если прерыване по уровню - то событие не "защелкивается", что вобщем-то  очевидно.

-----------

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

sadman41
Offline
Зарегистрирован: 19.10.2016

brokly пишет:

А чем усложнение чревато ?

А в чём смысл его лепить? Эффективности не добавится, ибо, как wdrakula заметил - всё завязано на релюшке со временем срабатывания в районе 10мс.

Можно, конечно, начать фантазировать на предмет того, что это не релюшка, а быстродействующий ключ, управляющий затвором фотонного излучателя в Большом Андронном Коллайдере и пр. и др.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

if (millis() - lastChange < timeOut) {

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

sadman41 пишет:

А в чём смысл его лепить?

А какова причина его отсутствия ? Лень ?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

sadman41 пишет:

А в чём смысл его лепить?

А какова причина его отсутствия ? Лень ?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Двоится...

sadman41
Offline
Зарегистрирован: 19.10.2016

Брукли, тебя лоджик покусал? Чего говниться на пустом месте-то? Пиши что хочешь туда, хоть классы по Квону.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Да нет. Просто довод "усложнение" не сильно правильный. Пытаюсь понять мотивацию. А она получается "виртуальная". Если ресурсов чипа хватает, то запрещать прерывание некрасиво. Буферизация, мьютексы, семафоры - вот правильные решения, все остальное от лени. Ну на крайняк сделай так, что бы учавствовали только атомарные буфера. Например получай от таймштампа только второй байт или первый. Для этой задачи такого подхода хватит "за глаза".

sadman41
Offline
Зарегистрирован: 19.10.2016

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

И, да, где-то тут еще честный Си должен промелькнуть.

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

brokly пишет:

 запрещать прерывание некрасиво.

Я так понимаю, что millis() ты не используешь никогда? (ну и всё остальное в wiring)

Ниже ее код, свеженький, только из wiring.c, там стандартное атомарное чтение 4-х байтовой переменной с запретом прерываний.

unsigned long millis()
{
	unsigned long m;
	uint8_t oldSREG = SREG;

	// disable interrupts while we read timer0_millis or we might get an
	// inconsistent value (e.g. in the middle of a write to timer0_millis)
	cli();
	m = timer0_millis;
	SREG = oldSREG;

	return m;
}

То Логику компилятор не нравиццо, то Архат, не к ночи помянутый, ООП проклинает...Теперь прерывания запрещать нельзя. Может что-то "в консерватории не так"?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

wdrakula пишет:

brokly пишет:

 запрещать прерывание некрасиво.

Я так понимаю, что millis() ты не используешь никогда? (ну и всё остальное в wiring)

Ниже ее код, свеженький, только из wiring.c, там стандартное атомарное чтение 4-х байтовой переменной с запретом прерываний.

unsigned long millis()
{
	unsigned long m;
	uint8_t oldSREG = SREG;

	// disable interrupts while we read timer0_millis or we might get an
	// inconsistent value (e.g. in the middle of a write to timer0_millis)
	cli();
	m = timer0_millis;
	SREG = oldSREG;

	return m;
}

То Логику компилятор не нравиццо, то Архат, не к ночи помянутый, ООП проклинает...Теперь прерывания запрещать нельзя. Может что-то "в консерватории не так"?

Использую, но не задумывался, что там у него внутри. И это, давайте без фанатизма. Я только озвучил свое мнение. Заметь никому ничего не навязываю, так что мягкое с теплым не путаем.

Green
Offline
Зарегистрирован: 01.10.2015

))Если нужны варианты - тут можно и без millis() и без запретов прерываний, если так уж принциально.)

promavto
Offline
Зарегистрирован: 30.04.2013

DIYMan пишет:

interrupts()

 DIYMan извини, я не думал что мое замечание вызовет столько споров. Ты же знаешь, я посравнению с тобой совсем не программист. Просто жалко стало interrupts(), а вдруг что то произойдет непредвиденное. А то сразу запрещать и не пущать. А о чем тема, наверное уже никто (в том числе и я) не помнит.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

promavto пишет:

DIYMan пишет:

interrupts()

 DIYMan извини, я не думал что мое замечание вызовет столько споров. Ты же знаешь, я посравнению с тобой совсем не программист. Просто жалко стало interrupts(), а вдруг что то произойдет непредвиденное. А то сразу запрещать и не пущать. А о чем тема, наверное уже никто (в том числе и я) не помнит.

Тут дело простое, пмсм: введение кольцевого буфера взамен атомарного чтения - это эдакий костылёк, который обязательно выстрелит в ногу тогда, когда не ждёшь. Навскидку пример: берём буфер размерностью 2, и запись в буфер из прерывания в 2 раза чаще, чем чтение из него. При таком варианте есть вероятность, что читать будем значение, которое в данный момент изменяется в прерывании. И смысл в том буфере тогда?

Увеличение размера буфера, безусловно, помогает, но только тем, что отдаляет проблему, вместо её решения. Атомарное чтение, пмсм - есть данность, без которой в некоторых случаях просто не обойтись.

Я так вижу, короче.