Главная » Микроконтроллеры
Призовой фонд
на июль 2018 г.
1. Регулируемый паяльник 60 Вт
Паяльник
2. 300 руб.
От пользователей

Похожие статьи:


Идеальная программа на С для МК - продолжение

Введение в продолжение

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

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

Разработка ПО тем более встроенного ПО всегда включает в себя этот этап верификации и уточнения задания. Будь оно сформулировано по всем правилам как техническое задание или выражено в виде некоторых пожеланий-предположений о требуемой функциональности устройства оно все равно требует проверки РЕАЛИЗУЕМОСТИ (feasibility по английски).

Уточнение понимания работы управляемой системы, ловушка очевидности

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

Система работает вот таким образом <здесь приводится "очевидное" описание>, потому что по другому сделать нельзя!

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

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

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

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

В конце концов я выяснил у автора задачи что прерыватель включается при появлении напряжения в цепи ламп поворотников (любых). То есть замыкание дополнительного ключа также включает прерыватель! Рис.2

Про состояния или проблема терминологии

В нашем случае можно определить:

  • состояние управляемой системы (назовем его RLC) которое МК получает ввиде 3-х битного слова по линиям inL, inR, inC;
  • состояния устройства которое МК формирует на выходах outR, outL;

Дело в том что вот это значение RLC кодирующее положение подрулевого рычага мы взяли и обозвали «состоянием», а это тянет и уводит нас в какие-то высшие сферы, дальние дали абстрактных мат.теорий о машинах состояний. Я предлагаю забыть слово состояние, и обзывать это значение «параметром» нашего алгоритма, это позволяет сосредоточиться на практических аспектах решения конкретной задачи!

Тем более есть глобальные состояния устройства, которые действительно важно различать:

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

Код с состояниями

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

Я бы main() написал вот так:

uint8_t rlCode;
uint8_t rlCodeSaved;
uint8_t count_pause;

int main(void)
{
   port_ini(); //инициализация портов

StartPoint:
   //начинаем с отключенными ключами устройства:
   PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));
   count_pause = 0;
   do{//ждем нажатия поворотника:
   rlCode = get_code();
   } while (!(rlCode == command_Right || rlCode == command_Left));
   //устройство переключается в активное состояние-замыкает дублирующий ключ,
   //который закодирован в rlCode:
   if (rlCode == command_Right) { PORTB |= (1 << RIGHT_OUT); }
   if (rlCode == command_Left) { PORTB |= (1 << LEFT_OUT); }
//мы продублировали замыкание цепи от подрулевого рычага!
   rlCodeSaved = rlCode;
   while (1)// цикл отсчета продленного кол-ва "морганий поворотника"
   {//--->LOOP
   do{//ждем переключения поворотника или паузу от прерывателя
   rlCode = get_code();//дребезг=command_Error тоже игнорируем:
//мы продублировали замыкание цепи от подрулевого рычага, поэтому
//если рычаг вернется в нейтральное положение условие все равно будет выполняться:
   } while (rlCode == rlCodeSaved || rlCode == command_Error);
   if (rlCode != command_Pause) goto StartPoint;
   count_pause++;//считаем разы продленного "моргания" на каждой паузе!
   if (count_pause == TURN_COUNT)
   {//rlCodeSaved хранит инфу о том какой поворотник мы включили!
   //но мы можем просто выключить оба здесь!
   PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));// отключили дублирование
// NO goto StartPoint; теперь мы должны дождаться когда отключат этот поворотник!
//чтобы повторно не включить удлиннение нажатия поворотника
   }
   do{
   rlCode = get_code();//ждем окончания паузы
   } while (rlCode == command_Pause || rlCode == command_Error);
//возвращаемся в //начало циклА отсчета продленного кол-ва "морганий поворотника"--->LOOP
   }
}

Идеальная программа???

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

Идеальной программа станет только тогда, когда будет проверена ее стабильная работа в реальном "железе", и ее работа удовлетворит пожелания заказчика разработки устройства, в какой бы форме эти пожелания не выражались!

К счастью я придумал второй критерий идеальности, который кажется на совсем банальный:

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

Мне кажется мой вариант программы удовлетворяет обоим этим критериям!

Теги:

Опубликована: 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (73) | Я собрал (0) | Подписаться

+1
andro #
Раз уж затронули эту тему, то по Вашему каким Вы считаете идеальным средством для разработки программ? Атмел студио отпадает, так как жрёт много ресурсов...
Ответить
0

[Автор]
ruhi #
Я с 1999 года работал в Атмел студии, меня она вполне устраивает. Сейчас работаю с 32-битными- SAME70 например, тоже в Атмел студии.
Особенно полезным был режим симуляции программ в процессоре. Очень помогает понять работу процессора.
Но 32-е процессоры и программы на них уже слишком сложны для симуляции.
Ответить
0
vavaav #
В замен Атмел студии я пользовался вот такой связкой. Для простых проектов очень простое решение.
Ответить
0

[Автор]
ruhi #
Это тоже: простое решение для тех, кто разгадал множество не простых секретов!
Ответить
+1
andro #
Тогда ещё был АВР Студио и он наверное не требовал столько ресурсов, но сегодняшний Атмел Студио очень прожорлив...
Ответить
0

[Автор]
ruhi #
Для симуляции, да, слабоват. Но на более менее больших проектах в симуляции уже нет смысла.
А для компиляции какая разница сколько ему ресурсов надо???
У меня комп хороший я не замечаю недостатка.
Или вы про что???
Ответить
+1
Goodefine #
Идеальная программа не должна содержать goto...
Ответить
0

[Автор]
ruhi #
Не уверен, что без goto код будет лучше, сравните:

...
while(1)//придется добавить этот цикл!
{
StartPoint:
//начинаем с отключенными ключами устройства:
PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));
count_pause = 0;
do{//ждем нажатия поворотника:
rlCode = get_code();
} while (!(rlCode == command_Right || rlCode == command_Left));
if (rlCode == command_Right) { PORTB |= (1 << RIGHT_OUT); }
if (rlCode == command_Left) { PORTB |= (1 << LEFT_OUT); }
rlCodeSaved = rlCode;
while (1)// цикл отсчета продленного кол-ва "морганий поворотника"
{//--->LOOP
do{//ждем переключения поворотника или паузу от прерывателя
rlCode = get_code();//дребезг=command_Error тоже игнорируем:
} while (rlCode == rlCodeSaved || rlCode == command_Error);
if (rlCode != command_Pause) break;
count_pause++;//считаем разы продленного "моргания" на каждой паузе!
if (count_pause == TURN_COUNT)
{//rlCodeSaved хранит инфу о том какой поворотник мы включили!
PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));// отключили дублирование
}
do{
rlCode = get_code();//ждем окончания паузы
} while (rlCode == command_Pause || rlCode == command_Error);
}
}
...
Ответить
0
Goodefine #
Не уверен, что без goto код будет лучше, сравните:
То что не лучше, так это не из-за отсутствия goto, а по некоторым другим причинам. Название громкое, а по факту тут идеальной программы даже близко нет.
Скорее наоборот - руководство, как не надо писать программы.
Например, подобные вещи:
PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));
Надо прятать за макросами. Смешанная стилистика написания:
rlCode, command_Right, StartPoint...
Комменты и код все в одной куче, без вменяемого форматирования (типа код компактный).
И если скажете что это придирки, то что скажете на этот шедевр:

do{//ждем нажатия поворотника:
rlCode = get_code();
} while (!(rlCode == command_Right || rlCode == command_Left));
И чего, если нужно добавить задачу контроллеру, типа еще кнопку опросить или диодом помигать, как из этого вечного цикла выходить.
Ждать пока rlCode правильным не станет? Переписывать всю логику? Легко модидифицируемая, ничего не скажешь.
В статье есть ссылка на код (с автоматом состояний), вот там уже вполне зрелая программа. А эту под таким заголовком
я бы постеснялся даже показывать
Ответить
0

[Автор]
ruhi #
Например, подобные вещи:
Надо прятать за макросами. Смешанная стилистика написания:
Вообще то я намеренно оставил конструкции из программы, которую вы назвали зрелой, что бы легче было сравнивать.
А чем вам не нравится ШедевР в трех строчках, не совсем понятно, зачем из этого цикла выходить что бы
еще кнопку опросить или диодом помигать
???
Ответить
0

[Автор]
ruhi #
Самое интересное, на мой взгляд, в этом коде, то что состояния кодируются последовательностью циклов while - каждый следующий while следующее состояние программы - не нужно заводить переменную, что бы хранить это состояние. Состояние задает позиция в программе - номер исполняемой строки!
И благодарю за анализ!
Ответить
0

[Автор]
ruhi #
Надо прятать за макросами...
...как из этого вечного цикла выходить.
Кстати, даже эти циклы-состояния можно макросом оформить, с передачей условий как параметра, но это следующий этап совершенствования кода, до которого обычно не доходит, когда код заработает! :)
Отредактирован 09.01.2018 10:48
Ответить
0
Goodefine #
Вы сами написали, что один из критериев - это:
Идеальная программа должна легко (то есть достаточно быстро) позволять удовлетворять вновь возникающие пожелания заказчика
В вечном цикле (и не одном по коду) программа тупо висит и ждет чего-то. И если заказчик попросит вас прикрутить еще какую-нибудь элементарную операцию, придется переделывать всю логику программы.
Самое интересное, на мой взгляд, в этом коде, то что состояния кодируются последовательностью циклов while - каждый следующий while следующее состояние программы - не нужно заводить переменную, что бы хранить это состояние.
Ну конечно, вместо гибкого автомата состояний будем просто висеть и чего то ждать. Они не кодируются этими циклами, эти циклы просто завешивают программу в этих местах.
Ответить
0

[Автор]
ruhi #
Что это за аргумент:
Они не кодируются этими циклами, эти циклы просто завешивают программу в этих местах.
непонятно!
Исходный "автомат состояний" также "завешивает программу в этих местах"!
Только при таком оформлении "эти места" четко видно, видна их последовательность, а в СВИЧЕ последовательность произвольная, никак не связана с реализуемым алгоритмом.
Эта произвольная последовательность это не гибкость, это бардак!
Отредактирован 10.01.2018 06:46
Ответить
0
Goodefine #
Вы простите, но у меня, чем дольше длится диалог, тем больше укрепляется мысль, что вашу статью нужно было назвать "Моя первая программа на Си".
В каком месте автомат завешивает программу? Автомат является частью вечного цикла, а не вечным циклом, например:

...
while(1)
{
state_machine();
//другой код, который выполнится
//в любом случае, независимо от состояния
//автомата
...
}
Пробежались по состояниям автомата, сделали что надо и дальше работать, а не висеть
Ответить
0
Goodefine #
а в СВИЧЕ последовательность произвольная, никак не связана с реализуемым алгоритмом.
Эта произвольная последовательность это не гибкость, это бардак!
Как раз наоборот, это очень удобно, разбиваете алгоритм на элементарные состояния, и описываете что делать в них при определенных условиях. И совершенно не важно, в какой они последовательности. Таким образом, очень удобно делать меню, задавать последовательность действий - например, управление внешним устройством по заданной программе, разбор протоколов и т.д. Например, стек TCP/IP (очень сложная штука) разбирается на автоматах состояний. Даже в ООП. А ваше решение - в лоб - вы еще просто не дошли до определенного уровня абстрактного видения задачи. Удивляет что вы отрицаете очевидные недостатки своей программы
Ответить
0

[Автор]
ruhi #
И совершенно не важно, в какой они последовательности.
Я точно знаю что последовательность как раз очень важна, например, ключи надо замыкать только при нажатии поворотника в данной задаче, а не когда вздумается. Если это не понятно то не о чем дальше говорить.
А ваше решение - в лоб - вы еще просто не дошли до определенного уровня абстрактного видения задачи
Я рад что вы "дошли до определенного уровня абстрактного видения задачи":

Вернетесь, поговорим :) !
Ответить
0
Goodefine #
Я точно знаю что последовательность как раз очень важна, например, ключи надо замыкать только при нажатии поворотника в данной задаче, а не когда вздумается. Если это не понятно то не о чем дальше говорить.
Последовательность состояний в свитче. А не последовательность событий приведших к этому состоянию.
Т.е. неважно

case RIGHT: //горит правый поворотник
...
case LEFT: //горит левый поворотник
Или

case LEFT: //горит левый поворотник
...
case RIGHT: //горит правый поворотник

Вернетесь, поговорим :) !
А по сути есть что сказать? По поводу завешивания программы? Это и есть главная "не идеальность". Что-то вы пропустили мимо ушей замечание, что автомат не завешивает программу, хотя напомните, кто писал:
Исходный "автомат состояний" также "завешивает программу в этих местах"!
Ответить
0

[Автор]
ruhi #
Вы передергиваете, там нет другой последовательности кроме последовательности перехода между состояниями! Вы не могли иметь ничего другого ввиду!!!
Вот вы даже состояния не корректные процитировали, не нужно разделять там RIGHT, LEFT, потому что достаточно знать что включилось, а что включено возвращается из предыдущего состояния "ВЫКЛЮЧЕНО" с выходом из этого предыдущего состояния.
То что надо выполнять "всегда", обычно пишется в прерываниях, приведите пример, я смогу ответить вам по существу этого примера!
А пока вопросы (или просто заявления?) не по существу, ответы соответствуют!
Отредактирован 10.01.2018 12:30
Ответить
0
Goodefine #
Вы передергиваете, там нет другой последовательности кроме последовательности перехода между состояниями! Вы не могли иметь ничего другого ввиду!!!
Точно не читатель:
Как раз наоборот, это очень удобно, разбиваете алгоритм на элементарные состояния, и описываете что делать в них при определенных условиях. И совершенно не важно, в какой они последовательности.
Я вам написал как строить автомат состояний, саму философию написания. Откройте же шоры с глаз наконец, состояний может быть несколько десятков. А в вашей идеальной программе с каждой новой задачей код будет превращаться в несопровождаемое ...о.
То что надо выполнять "всегда", обычно пишется в прерываниях
О, уже до прерываний дошли. Еще и обычно...
Это плоды "идеального" подхода к завешиванию.
приведите пример, я смогу ответить вам по существу этого примера!
Да хоть добавьте вежливую кнопку, мигающую аварийкой три раза - будете бегать по всей программе.
Ответить
0

[Автор]
ruhi #
Да успокойтесь вы, у меня никогда ничего не висит даже в многопоточных фильтрах под DirectShow.
И еще раз повторяю, если для вас не важен порядок перехода между состояниями или он вообще для вас не существует, то разговаривать не о чем :( !
Счастливого пребывания вам, на "определенном уровне абстрактного видения задачи"!
Ответить
0
Goodefine #
... у меня никогда ничего не висит даже в многопоточных фильтрах под DirectShow.
Речь не о фильтрах или прочей лабуде. Как космические корабли бороздят просторы Вселенной рассказывать не надо.
Есть конкретная статья, с конкретным кодом и громким названием. Код не соответствует вами же предложенному критерию, поскольку полностью выключает из работы основной вечный цикл, и вместо того, чтобы в будущем при необходимости просто добавить новую задачу в тело while(1), придется трогать (и не слабо) код уже написанной и отлаженной задачи. Более того, код противопоставлен добротному коду на автомате состояний (отсюда такое внимание автомату) Так понятно?
И еще раз повторяю, если для вас не важен порядок перехода между состояниями или он вообще для вас не существует, то разговаривать не о чем :( !
Повторяю в третий раз - порядок перехода важен, он задается логикой перехода по состояниям автомата. И в автомате прекрасно кодируется порядок перехода - тот же разбор протокола, где каждый одинаковый байт может иметь разное значение, в зависимости от того, какие байты пришли до этого. И автомат с этим прекрасно и наглядно справляется. А неважен сам порядок описания этих состояний. Это позволяет при необходимости просто ниже добавить новое состояние и описать его. Не нужно перелопачивать уже написанный и работающий код. Вы этого не понимаете или притворяетесь?
Счастливого пребывания вам, на "определенном уровне абстрактного видения задачи"!
Имеющий уши услышит, я понимаю и вижу ваш труд по статье, анализ неплохой, но код никуда не годится. Паттерн проектирования, как модно говорить, в корне не верен. Ведь статья для новичков, которые могут перенести шаблон на свои программы, а потом ходить по граблям.
Ответить
0

[Автор]
ruhi #
Речь не о фильтрах или прочей лабуде. Как космические корабли бороздят просторы Вселенной рассказывать не надо.
Вам, значит, можно про TCP/IP рассказывать, а мне вы про фильтры запрещаете.
Может вам легче совсем сайт закрыть, что бы он не раздражал вас чужими мнениями, отличными от вашего?
Вы запросто определяете что тот код добротный, а этот на О, я рад за вас!
Но я так пишу уже больше 10 лет, и точно знаю что если вы действительно попробуете добавить какое то расширение функциональности, в эти два варианта программы, то в моей версии это будет проще и абсолютно прозрачно по отношению к закодированному "порядку перехода между состояниями", которого в ваших CASE-ах надо еще поискать!
Ответить
0

[Автор]
ruhi #
неважен сам порядок описания этих состояний.
Важен порядок ПЕРЕХОДА между состояниями! Я показал как порядок описания этих состояний позволяет кодировать и контролировать и визуализировать порядок ПЕРЕХОДА между состояниями!
Вы всегда должны проверить при добавлении новой функциональности, что эта новая функциональность не мешает правильному переходу между состояниями!
А если вы добавляете новое состояние как вы ищете все состояния из которых будет переход в это новое состояние, и все те в которые будет выход из этого нового состояния, попробуйте ответить?
А еще как добавить разные действия для переходов из одного состояния в разные? А если должно быть определенное действие при входе в данное состояние?
Что важнее иметь возможность реализовать все эти варианты или иметь одну возможность
добавить новую задачу в тело while(1)
?
Ответить
0
Goodefine #
Важен порядок ПЕРЕХОДА между состояниями! Я показал как порядок описания этих состояний позволяет кодировать и контролировать и визуализировать порядок ПЕРЕХОДА между состояниями!
Никто не спорит что порядок перехода важен. Автомат справляется с этим на ура. А визуализация это к программам типа алгоритм билдера. До определенного уровня вроде удобно, потом громоздко, а потом нечитаемо и несопровождаемо.
А если вы добавляете новое состояние как вы ищете все состояния из которых будет переход в это новое состояние, и все те в которые будет выход из этого нового состояния, попробуйте ответить?
Легче один раз показать. Этот код я писал около семи лет назад. Он ни в коем случае не претендует на роль идеального. Распознаваемые протоколы добавлялись последовательно, по мере появления исследуемых пультов. Распознавание делалось на автоматах - там их несколько. Но они прекрасно уживаются между собой и дополняют друг друга. И не мешают вечному циклу, в котором крутится помимо всего прочего обработка задач usb протокола. При распознавании протокола даже прерывания не использовались, только чтение флага - чтобы не мешать критичной по времени обработке usb пакетов. Хотелось чтобы вы на словах рассказали как бы решили эту задачу на методах своей десятилетней практики.
Что важнее иметь возможность реализовать все эти варианты или иметь одну возможность
"добавить новую задачу в тело while(1)"
Реализовать это все можно и без нивелирования вечного цикла, в который может потребоваться необходимость добавить не одну, а десяток задач
Ответить
0

[Автор]
ruhi #
Хорошо! Вообще я вам благодарен за то что вы побуждаете меня писать пояснения!
Никто не спорит что порядок перехода важен. Автомат справляется с этим на ура. А визуализация это к программам типа алгоритм билдера. До определенного уровня вроде удобно, потом громоздко, а потом нечитаемо и несопровождаемо.
Вопрос не в том с чем не справляется или справляется автомат, вопрос как раз с читаемостью и затратами на сопровождение!
Я только могу вас заверить что если писать блоками:

[-действие перед входом в состояние-]
do{
[- и пожалуйста здесь вызов общей для всех состояний функции-]
[-периодическое-постоянное действие в состоянии-]
}while(условие выхода)
[-действие после выхода из состояния-]
[-логика выбора следующего состояния-]
то все очень хорошо читается и сопровождается!
Мог бы показать это на примерах, но это книга получится, а не статья, а я со статьей уже утомился :) !
Отредактирован 12.01.2018 11:02
Ответить
0

[Автор]
ruhi #
кстати, по поводу
в который может потребоваться необходимость добавить не одну, а десяток задач
В этом конкретном решении вы можете заметить, что функция:
get_code()
вызывается в каждом состоянии, то есть ВСЕГДА(как вам и хотелось!), как то что в вашем подходе вы пишите перед свичом! Добавляйте туда все что вам нужно ВСЕГДА!
Расширяй - не хочу, что называется!
Ответить
0
Goodefine #
вызывается в каждом состоянии, то есть ВСЕГДА(как вам и хотелось!), как то что в вашем подходе вы пишите перед свичом! Добавляйте туда все что вам нужно ВСЕГДА!
А как же принцип разделения задач? get_code() подразумевает опрос пинов, аля клавиатура. Если туда пихать все остальное... Ну вы понимаете. Возьму и вставлю туда, ибо больше некуда очередной do-while ))
то все очень хорошо читается и сопровождается!
Если у вас будет время и желание поясните, хотя бы на словах, как бы вы написали код из моей статьи своими блоками do-while. Мне это действительно интересно.
Вопрос не в том с чем не справляется или справляется автомат, вопрос как раз с читаемостью и затратами на сопровождение!
Это называется каждый остался при своем мнении. Что-же, имеем право.
Ответить
0

[Автор]
ruhi #
Ну вы понимаете. Возьму и вставлю туда, ибо больше некуда очередной do-while ))
нельзя туда очередной do-while пихать! внешний не будет работать!
Потом неужели трудно догадаться что не обязательно внутрь get_code() все пихать, есть же места откуда вызываются все функции get_code(), там было:
[- и пожалуйста здесь вызов общей для всех состояний функции-]

Если у вас будет время и желание поясните, хотя бы на словах, как бы вы написали код из моей статьи своими блоками do-while. Мне это действительно интересно.
У меня ваш проект моя Атмел-студия не понимает, беда у них с обратной совместимостью.
Но проект интересный, ЮСБ программно реализован на ассемблере, я попробую расковырять на досуге!
Отредактирован 13.01.2018 13:07
Ответить
0
Goodefine #
нельзя туда очередной do-while пихать! внешний не будет работать!
Естественно нельзя. Потому и говорю. Вы ж сказали, зачем вечный цикл, есть get_code. Тем более, допустим, парадигма do-while понравилась и хочется еще куда-нибудь очередной зависон применить.
Потом неужели трудно догадаться что не обязательно внутрь get_code() все пихать, есть же места откуда вызываются все функции get_code()
Ага, это в каждую из трех do{} дублирующий код писать? Ибо неизвестно где повиснем.
Ответить
0

[Автор]
ruhi #
Кстати, стек TCP/IP не такая уж сложная штука (в библиотеке LWIP, например, не больше сотни файлов).
Так вот СВИТЧ с состояниями (которые вы видимо имели ввиду) там убрался в одной функции, а вся основная работа к нему, в общем то, отношения не имеет.
Ответить
0
Goodefine #
Кстати, стек TCP/IP не такая уж сложная штука (в библиотеке LWIP, например, не больше сотни файлов).
Насмешили. Скажете это когда напишите подобный стек. Пока я вижу блуждание в двух строчках кода.
Так вот СВИТЧ с состояниями (которые вы видимо имели ввиду) там убрался в одной функции
Я думал что читаете вы лучше чем пишите. Там свитчей самых разных, которыми парсятся протоколы и пакеты, более чем в сорока разных файлах
Ответить
0
smack #
Goodefine
Препроцессор повсеместно использовать тоже не есть хорошо. Препроцессор создает поля в глобальной области, как вследствие все будет сидеть в куче-перерасход ОЗУ.
Ответить
0

[Автор]
ruhi #
Что то уж вы загнули:
Препроцессор создает поля в глобальной области
ОЗУ расходуется только (в основном?) при определении переменных. Определения переменных дефайнами никто не вводит (обычно).
Ответить
0
Goodefine #
Директивы препроцессора разные бывают,
если в виде

#define PIN_ENABLE(x) PORTB|=(1<<x)
Может чего и съест, это аналог функции, а в виде

#define LEFT_ENABLE PORTB |= (1 << LEFT_OUT)
накладных расходов вообще нет. Зато можно вынести всю аппаратно-зависимую часть в один файл, со всеми вытекающими плюсами. Да и код легче читается
Ответить
+1
Pauk #
Я задавал вопрос в предыдущей статье, но раз есть продолжение, то повторю здесь, так как кажется никто не понял. Вопрос относится не только к автору, но так же просьба отозваться всем, кто знает. На микроконтроллере нужно организовать несколько элементов И. Как это сделать, что бы было правда идеально, желательно без прерываний. Логика такая: выходной сигнал должен появляться после наличия сигнала одновременно на двух входах, и должен пропадать при исчезновении сигнала на любом из входов.
Ответить
0

[Автор]
ruhi #
Так маленько понятнее!
ДЫк вот эта программа и реализует логическую функцию (более сложную чем элемент И)!
Тут в зависимости от состояния 3-х входных ног/битов меняется состояние 2-х выходных ног/битов.
Вопрос во времени срабатывания этого элемента логической функции,
Логика такая: выходной сигнал должен появляться после наличия сигнала одновременно на двух входах
Через какое время он должен появляться(не более чем)??? То есть как быстро элементы И должны менять выходной сигнал при изменении входных?
5 микро секунд допустимая задержка???
например.
Ответить
+1
Pauk #
Многовато и в моём случае это критично. Максимум 2 микросекунды.
Ответить
0

[Автор]
ruhi #
В принципе можно что то изобразить и на 2 мкс, если тактовая частота процессора 16МГц (а лучше 20 и т.д.) скажем, но будет работать только эта логическая функция, ничего больше запихнуть в основной цикл не получится при таком ограничении по времени, на время работы этой логической функции.
Потом на Xmega -х, кажется, можно такую логику как аппаратную между пинами сконфигурировать для этих целей.
И Интересно было бы узнать исходную задачу, а не то чем вы ее собираетесь решать.
Ответить
0
Pauk #
Нужно два быстрых элемента "И" и одновибратор. Можно использовать серию 155 у которой время срабатывания даже меньше получается, но не подходит по энергопотреблению. Хотелось бы сделать это на Attiny13.
Ответить
0

[Автор]
ruhi #
Можожно сделать так:
loop1:
in reg1, porta; 1-tick
in reg2, portb; 1-tick
and reg1, reg2; 1-tick
right-shift reg1; 1-tick
out portB, reg1; 1-tick
rjmp loop1; 2-tick

На частоте 16 MHz это 7/16 секунды(7 ticks), входы элемента И должны быть на одинаковых пинах условных портов A and B, а выходы след. По старшинству биты-пины
Про одновибратор надо уточнить длину импульса и запускающее событие, можно на счётчике сделать аппаратно-парралельно.
А выход из цикла, для какой то настройки например, по прерыванию от кнопки!
Ответить
+1
andro #
А при чём здесь ассемблер?
Ответить
0

[Автор]
ruhi #
Это хороший вопрос!
Ответить
+1

[Автор]
ruhi #
Тут приведен на ассемблере код, который реализует два «элемента И» на АВР со временем срабатывания около 1мкс(выше пропустил мк, торопился), в зависимости от тактовой частоты МК.
Только сейчас посмотрел про Attiny13, у нее же только 6 ног доступно! Это ж получается только на два элемента И хватит! Про одновибратор тогда совсем не понятно!
И цикл надо переделать на использование только одного порта. (Я там кстати ошибся: in regx, PINx - должно быть, а right-shift это LSR)
В общем на ассемблере можно написать «два элемента И» со временем срабатывания не более 1.5мкс (может даже до 1мкс, ТОЧНО можно!) даже на 10МГц при произвольном расположении ног на одном порту. Можно объявить конкурс для знатоков AVR-ассемблера :). Я бы мог передать запороленный ZIP с ответами, тому кто может предложить свой вариант.
Ответить
+1
Pauk #
Огромное спасибо Вам за внимание. На счёт одновибратора - он должен быть на одном из входов элемента И. Сейчас поясню: первый вывод элемента И должен иметь высший приоритет и сразу же снимать высокий уровень с выхода (наши 3 мкс.), а при подаче сигнала любой длительности на второй вход он должен преобразовываться в импульс длительностью 200 мс. Логика такова - на вывод 1 подаётся высокий уривень, а затем сигнал на вывод 2 и вместе с этим должен установится высокий уровень на выходе в течении 200 мс, но он должен стать низким до истечения этого времени, если пропадёт высокий уровень на входе 1 (смотрите рисунок). Таких элементов нужно два на микроконтроллер, думаю ног достаточно. И пожалуйста приведите пример на С. Я не смогу сделать это на ассемблере.
Прикрепленный файл: Scan.jpg
Ответить
0

[Автор]
ruhi #
На С это нельзя написать! Нельзя гарантировать-рассчитать-задать время срабатывания!
Это прямое управление аппаратными возможностями процессора, С для этого не предназначен, по определению!
Это вопрос знания-понимания аппаратных возможностей контроллера (периферия, конвеер, шины) и возможностей управления ими (регистры, ассемблер). К языку-С это отношения не имеет.
Потом на ассемблере это и проще - это всего пара десятков инструкций!
Потом это у вас все таки более сложный элемент - не просто И, одновибратор с разрешением ?!
Надо точно требования по временам выписать:
вход разрешения - тут2(!) максимума по задержкам туда и обратно, а может и не 2 а больше + в зависимости от состояния входа одновибратора;
вход включения импульса если пропадает 1 - выходной импульс тоже снимать? или он уже не влияет 200мс, срабатывать по фронту(через какое время фронт фиксировать?) или по импульсу(какой минимальной длинны?)
...
Обычно диаграмму входных-выходных сигналов рисуют с указанием максимальных/минимальных времен.
Тоже можно от руки!
Ответить
0
Pauk #
Может всё таки лучше на логике собирать? Но существенный фактор энергосбережение!
Ответить
0

[Автор]
ruhi #
Может всё таки лучше на логике собирать?
Нарисованные диаграммы вам в любом случае не помешают.
Там еще надежность падает с количеством корпусов, соединений, паек, сложность-цена изготовления растет и т д, и т п
Да напишу я вам 20-40 инструкций, нарисуйте диаграммы!
Ответить
0
Pauk #
Ну вот как то вот так, ин2 - это вход одновибратора, а оут2 его выход. Понятно что нибудь из моих диаграмм?
Прикрепленный файл: Scan.jpg
Ответить
0

[Автор]
ruhi #
Да! В таком виде, но поподробнее, еще фронты надо отдельно увеличено нарисовать, чтобы требования к времени срабатывания показать.
И, вообще то, должно быть 3-сигнала, а у вас почему то четыре.
1) - сигнал, я так понимаю разрешение, правильно?
Должно быть штуки 4 - диаграмм, не меньше!
Можно в личку.
Ответить
0
Pauk #
Я не представляю как это может быть сделано на микроконтроллере, но на логических элементах я бы сделал вот так(смотрите рисунок). Да, и были проведены более точные рассчёты и скорость переключения может быть до 100 мкс, но главный фактор остаётся энергопотребление, желательно как можно экономичнее. Это логика устройства в целом. Сигнал на входе 1 или 2 запускает ждущий мультивибратор на время 200-300 мс, выходные сигналы зависят от наличия сигналов на входах.
Отредактирован 08.02.2018 13:01
Прикрепленный файл: 2ili-jm-5i.jpg
Ответить
0

[Автор]
ruhi #
in3 тоже по и складывается с in1 и выходом ЖМ? Это для верхнего И разрешение? Только для верхнего?
И, все таки, нужно знать допустимое время задержки срабатывания, если in1 переключается в ОДИН какая максимальная задержка допустима до реакции out1, out2? Скажем 3 мксекунды (это с запасом) устроит?
И наоборот когда in1 или in2, in3 переключаются в НОЛЬ, раз там И стоит, они переключают его выход в НОЛЬ, тот же Вопрос: какая максимальная задержка допустима до реакции out1, out2? Скажем 3 мксекунды (это с запасом) устроит?
Ответить
0

[Автор]
ruhi #
главный фактор остаётся энергопотребление
Вы кстати из какой цифры исходите?
Я вижу:Power Supply Current
Active 8MHz, VCC = 5V
Max. = 12 mA
12 mA устраивают?
Ответить
0
Pauk #
Да, Вы всё правильно поняли. Главное быстродействие здесь в течении 100 мкс снять высокий уровень с выхода 1 при пропадании высокого уровня на входе 3. На счёт потребления желательно минимальный вариант из даташита на Аттини13 где то до 0,3 мА.

Active Mode:1 MHz, 1.8V: 240µA
Отредактирован 09.02.2018 09:52
Ответить
+2

[Автор]
ruhi #
Я исходил из 10МГц тактовой частоты, для 1Мгц, соответственно, время будет в 10 раз больше, то есть 3мкс превращаются в 30-ть, но если надо успеть за 100 то это вроде бы приемлемо!?
По работе ЖМ еще вопросы будут:
он включается фронтом или уровнем?
То есть когда с ИЛИ приходит переключение с 0-ля в 1-цу ЖМ переключает выход в 1-цу на 200мс, а если за эти 200мс 1-ца пропадет у него на входе что он должен делать с выходом?
А если 1-пропадет и снова появится?...
А еще, если 200мс прошли, а 1-ца на входе не пропала, что у ЖМ на выходе должно быть?
Отредактирован 09.02.2018 14:10
Ответить
0

[Автор]
ruhi #
Еще: на частоте один МГц надо учитывать что если входной импульс будет меньше 30мкс ЖМ не включится, то есть между любыми 2-мя последовательными фронтами на одной линии не должно быть меньше 30мкс. Сигналы должны быть чистыми, фронты резкими!
Ответить
0
Pauk #
если надо успеть за 100 то это вроде бы приемлемо!?
Да, нормально.

когда с ИЛИ приходит переключение с 0-ля в 1-цу ЖМ переключает выход в 1-цу на 200мс, а если за эти 200мс 1-ца пропадет у него на входе что он должен делать с выходом?
Когда с ИЛИ приходит переключение с 0-ля в 1-цу ЖМ переключает выход в 1-цу на 200мс, и никакой входной сигнал в дальнейшем не должен влиять на это до тех пор, пока не пропадёт единица на входе 3, но если вход 3 переключится в ноль до завершения 200 мс, то выход 2 тоже должен переключиться в ноль в течении 100 мкс.

А если 1-пропадет и снова появится?...
А еще, если 200мс прошли, а 1-ца на входе не пропала, что у ЖМ на выходе должно быть?
ЖМ должен завершить период 200 мс и если единица снова появится после этого времени, то цикл должен повториться, но если единица на входе 1 не пропадала, то ничего делать не надо.

Не слишком запутанно, можно понять?
Отредактирован 10.02.2018 13:34
Ответить
0

[Автор]
ruhi #
ЖМ должен завершить период 200 мс и если единица снова появится
еще:
получается что надо чтобы импульс любой длительности на входе1(например) укорачивался до 200мс,
то есть:
вход1 переключился из 0-ля в 1-цу;
выход1 переключился в 1-цу тоже (вход3 пока не рассматриваем - всегда 1-ца!);
если вход1 уйдет в 0-ль рагьше 200мс, оконечное И сделает 0-ль на вЫходе1 по любому!
а если вход1 остается 1-ца дольше 200мс, ты написал
но если единица на входе 1 не пропадала, то ничего делать не надо
ЖМ должен оставить 1-цу пока вход1 остается 1-цей,
то есть получается:
выход1 просто повторяет вход1 (вход3=1 напоминаю),
зачем тут ЖМ НЕ ПОНЯТНО поэтому!!!
Отредактирован 11.02.2018 00:13
Ответить
0

[Автор]
ruhi #
но если вход 3 переключится в ноль до завершения 200 мс
то есть вход3 управляет обоими И?
значит пока на вход3 стоит 0-ль на обоих выходах должен быть 0-ль, не зависимо от значения на входах 1,2, правильно?
Тогда должен ли ЖМ запускаться когда вход3=0???
то есть:
вход3=0
вход1,2 переключились в 01/10/11 (выбирай!)
выходы1,2 остались 00???
через 50мс вход3 стал1-ца!
выходы1,2 переключаются в 01/10/11 на 200мс --ИЛИ-- на 150мс (потому что ЖМ запустился 50мс назад пока вход3 был =0)?????????????
Ответить
0
Pauk #
Я наверное неясно выразился, вход 3 не действует на выход 2 - это видно из схемы, импульс любой длительности на входах, после ЖМ должен иметь длину 200 мс, если импульс на входе длиннее или короче этого времени по любому после Жм должен быть импульс 200 мс, ничего делать не надо - я имел в виду именно это, входной импульс не должен влиять на выходной, только пропадание единицы на входе 3 сразу переключает выход 1 в низкий уровень. ЖМ должен запускаться с каждым входным импульсом, но только после завершения своего цикла. Я могу нарисовать и собрать данную схему на транзисторах если угодно, но как быть с микроконтроллером?
Ответить
0

[Автор]
ruhi #
вход 3 не действует на выход 2 - это видно из схемы
С этим понятно- разобрались!
импульс любой длительности на входах, после ЖМ должен иметь длину 200 мс
По схеме которую вы нарисовали в ЖМ смысла нет (не вижу-не понимаю)!
Удлинить входной короткий импульс (на любом из выходов 1,2) он не может, потому что на выходе элементы-И стоят.
Если он должен обрезать длинные входные импульсы - так это как то не вяжется с вашими пояснениями.
Опишите хоть одну ситуацию, когда видно что ЖМ действительно работает (удлиняет импульс/фронт или он должен, все таки, обрезать или и то и другое?), когда видно что ЖМ действительно нужен!
Попробуйте рассуждать как я:
на вход-2 пришла 1-ца на 50 мс, на выходе 2 появится 1-ца на 50 мс, так? что будет через 50мс??? если эти 50мс теперь заменить на 350мс - какой сигнал должен быть на выходе-2???
Достаточно эти два варианта расписать, кажется!!!
Отредактирован 12.02.2018 12:42
Ответить
0

[Автор]
ruhi #
Еще так можно:
ЖМ должен запускаться с каждым входным импульсом, но только после завершения своего цикла.
на вход-2 пришла 1-ца на 50 мс, на выходе 2 появится 1-ца на 50 мс, так?
дальше на вход-2 стоит 0-ль 50 мс, на выходе 2 0-ль на 50 мс, так?
снова на вход-2 пришла 1-ца на 50 мс, на выходе 2 опять 1-ЦА на 50 мс, так?
Ну никак не видно здесь необходимости применения ЖМ - схема будет так же работать, если его просто закоротить, кажется! Или я чего то не понимаю, что то упускаю??? Что?

Я понимаю что для исходной функции он, наверно, нужен! Но логику вы похоже не правильно нарисовали, по тому что в ней он смысла не имеет.
Отредактирован 12.02.2018 13:36
Ответить
+1
Pauk #
А вот теперь Вы нашли ошибку, я хотел упростить и использовать один ЖМ на оба канала, но не получилось. Пришлось оставить независимый ЖМ на каждый канал и добавить некоторые элементы(смотрите рисунок). Добавился вход 4(инвертирующий) и вход 5, а ещё если на одном выходе высокий уровень, то сигнал на другом входе не должен действовать на его выход. Надеюсь теперь без ошибок, простите что завёл в заблуждение, ошибка появилась после добавления второго канала.
Прикрепленный файл: 12.02.18.jpg
Ответить
0

[Автор]
ruhi #
Так это уже 7 ног. В Attiny13 уже не влезает!
Напишите, все таки, исходную задачу (если секретно, то в личку, ни кому не расскажу!) зачем нужно устройство, а не ваше решение и я смогу предложить вам варианты решения: программные или на логических элементах или комбинированные,
-ИЛИ-
нужны диаграммы входных/выходных сигналов (как я и просил сначала)!
Потому что где гарантия что эта схема без ошибки?
Мне надо убедиться что задача корректно поставлена иначе нет смысла ее решать!
Кстати, у автора задачи по которой написана статья, схема сначала тоже секретная была, а потом он ее выложил, чтобы тип транзистора ему проверили-подсказали!
Ответить
0
Pauk #
Устройство представляет собой ответственный узел дистанционной тормозной системы. На рисунке показана оконечная исполнительная часть. Двигатель с червячной передачей передвигает задвижку в виде пластины, при достижении конца хода которой замыкаются концевики. Закрывание разрешается включением тумблера, открывание возможно независимо от положения тумблера. Хотя и имеются концевики, нужен некоторый фиксированный период вращения двигателя около 200 мс для надёжной его остановки при отказе концевика во избежание заклинивания. В промежутке передвижения пластины имеется датчик, который будет давать сигнал при несанкционированном аварийном открытии. Это должно произойти если датчик сработает до подачи управляющего сигнала на контроллер. Управляющие сигналы будут формироватся приёмным модулем дистанционного управления, в перспективе задумка на RFID. Если что не понятно жду вопросов.
Прикрепленный файл: 23.02.18.jpg
Ответить
0

[Автор]
ruhi #
На самом деле мало что понятно, давайте попробуем разобраться.
1.Движение в сторону закрытия должно быть запрещено если тумблер ВЫключен???
2.
В промежутке передвижения пластины имеется датчик, который будет давать сигнал при несанкционированном аварийном открытии.
Значит ли это что: Датчик сигнализирует движение в сторону закрытия при ВЫключенном тумблере, то есть сигнализирует о том что запрещено???
3.
Хотя и имеются концевики, нужен некоторый фиксированный период вращения двигателя около 200 мс для надёжной его остановки при отказе концевика во избежание заклинивания.
Концевик должен остановить движение (в свою сторону? их по одному с двух концов?), выдать сигнал на остановку, правильно??? Если концевик отказал, сигнал НЕ поступит, откуда отсчитывать 200мс???
4.Управляющие сигналы это сигнал открытия(in1) и сигнал на закрытие(in2), который срабатывает(действует) только если ВКЛючен тумблер, правильно???
Ответить
0

[Автор]
ruhi #
Да! Все равно надо ответить на вопрос:
Если включение пришло на in1 и in2 одновременно,
(что то замкнуло, например, нештатные ситуации тоже подлежат рассмотрению!)
То есть имеем одновременно сигнал открыть и закрыть, КАК должен вести себя двигатель??? - вы должны определиться - это тоже важно и с точки зрения реализуемой логики и с точки зрения безопасности и/или минимизации ущерба от нештатной ситуации!
Ответить
0
Pauk #
Спасибо, я ждал этих вопросов. На самом деле Вы всё поняли. Уточню некоторые детали:
1) Движение в сторону закрытия должно быть запрещено если тумблер ВЫключен, но тумблер не влияет на открытие.
2) Датчик должен сигнализировать, если он сработал при замкнутом концевике 1.
3) Пока что концевик один, только в сторону закрытия, так как заклинивание может произойти при закрытие, но планируется как нибудь примастерить концевик и на открытие. Вы правильно поняли, концевик останавливает движени в свою сторону. 200 мс отсчитываются с момента прихода сигнала на открытие или закрытие.
4) Тумблер запрещает только закрытие, на открытие он не действует, что бы в нештатной ситуации всегда была возможность открыть.

Если включение пришло на in1 и in2 одновременно
Тот вход , который сработает первым должен запрещать срабатывание второго входа до окончания своего цикла.
Ответить
0

[Автор]
ruhi #
Хорошо, мы дошли до более сложных вопросов:
2) Датчик должен сигнализировать, если он сработал при замкнутом концевике 1.
А кто ОН-то: датчик, тумблер или концевик??? НО!:
судя по всему датчик и концевик это одно и то же, потому что и тот и другой выдают сигнал о закрытии, значит это одно и то же устройство!
Просто есть два варианта срабатывания датчика во времени относительно состояния тумблера:
1.тумблер ВКЛючен, через некоторое время происходит закрытие - это точно АВАРИЯ-запрещенное переключение!
2. включаем тумблер когда система УЖЕ находится в закрытом состоянии - вы должны сказать, выдавать здесь АВАРИю или это допустимая ситуация!!!???

Тот вход , который сработает первым должен запрещать срабатывание второго входа до окончания своего цикла.
этого не достаточно, процессор может не увидеть какой первым включился, он прочитает их обоих уже включенными!
Надо все равно, вам(!), определить приоритет!!!
Я подскажу, раз
в нештатной ситуации всегда была возможность открыть.
скорее всего приоритет должен быть у открытия, поскольку это тоже не штатная ситуация когда непонятно что происходит с сигналами управления!!!
И посчитаем сигналы:
1.тумблер
2.in1
3.in2
4.концевик закрытия (end)
5.концевик ОТкрытия (start- так он есть или будет :)
6.ВЫХОД: двигатель стоп или закрываем
7.ВЫХОД: двигатель стоп или ОТкрываем

Получается что бы убралось на 6-ть ног надо или
концевик ОТкрытия исключить все таки,
или
какую-то логику все же поставить
или
взять чип с большим кол-вом ног!!!
Ответить
0
Pauk #
А кто ОН-то
конечно же датчик.

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

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

На счёт приоритета Вы правы, но всё же лучше что бы процессор определял какой будет первым.

Я постараюсь установить концевик открытия, но не знаю насколько это возможно.

Я подумал на счёт количества ног и решил купить готовое устройство на АтМега88, но программу всё равно придётся писать.
Отредактирован 26.02.2018 14:21
Ответить
0

[Автор]
ruhi #
Ага, то есть датчик показывает начало закрытия, а концевик сообщает что окончательно закрыто, так?
А про датчик движения все равно не понятно - это еще один датчик?
Но, значит, в любом случае, еще один сигнал с датчика будет, он будет 8-ой.
А в общем, если это сигналы с механики, это все должно быть достаточно медленно, что бы на С-реализовать.
Ответить
+1
Pauk #
Ну что же тут непонятно - датчик движения пластины сигнализирует об аварийном открытии тормоза.
Всего 9 портов:
1) тумблер,
2) концевик закрытия,
3) концевик открытия,
4) датчик движения пластины,
5) вход сигнала закрытия,
6) вход сигнала открытия,
7) выход сигнала закрытия,
8) выход сигнала открытия,
9) выход сигнала аварии.

Думаю пока всё. Мы столько с Вами говорили, Вы можете привести хоть один пример для этого?
Ответить
0

[Автор]
ruhi #
Пример кода??? Так вы даже с процессором не определились еще! Я уж не говорю о полной схемотехнике!
Если бы это был разговор а не переписка, он состоялся бы в течении полчаса, максимум час!
Это все еще самое начало, то есть мы только подходим к формулировке технического задания. И эта формулировка еще будет предварительная! Потому что,что бы выяснить технические параметры окончательно, надо написать программу которая позволяет их измерить и подтвердить или скорректировать.
После чего уже можно написать окончательную версию алгоритма!
Бывает конечно что можно попасть в цель с первой реализации. но вероятность достаточно мала, и лучше на это не рассчитывать!
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическое сопротивление?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

AVR-программатор USB ASP
AVR-программатор USB ASP
Мини гравер 125 Ватт Конструктор для сборки: предусилитель на лампе 6N3
вверх