Как стать автором
Обновить

Комментарии 44

маркетинговая ловушка. Надо было 1-wire еще и в тэги добавить, но пока держусь :)
вообще, при нынешних ценах на чипы, можно запросто рядом с каждой кнопкой расположить какую-нибудь тиньку, которая принимала-отправляла бы команды модуляцией по питающему проводу
Я так поглядел, 1-Wire Slave довольно костыльно реализуется, а жаль.
что-то шутки даже со смайлом в конце предложения идут не очень — добавил определенности, закавычив широкоизвестное название протокола во избежание нежелательных ассоциаций.

А вообще, в данном случае достаточно именно «проволочного» решения на «клиентской стороне» — без всяких контроллеров в кнопках as long as все можно сделать аппаратно-программно на «сервере»
так, на всякий случай, если кому-то интересно
человечек сделал клиента 1w на avr
avr.ru/ready/measure/mass/debet/part3
Да их кто только не делал, и я в том числе (это следующий уровень после миганий светодиодами). Дать код на ассемблере? :)
дать!
хабр индексируется лучше очень многих ресурсов — легче найти новичкам
Только вряд ли кому поможет кусок, вырванный из контекста, но ладно:

Код
; задержка в 1 микросекунду (максимально достижимой точности!!!)               
; учитывается длительность RCALL и RET                                         
; НЕ ДОЛЖНА ИСПОЛЬЗОВАТЬ НИ ОДНОГО РЕГИСТРА !!!!                               
; для низкой тактовой частоты, возможно, придется заменить на макрос из NOP-ов 
delay1us:                                                                   
;          +3                     
  nop      ;1                  
  push r0  ;2                                                                  
  pop r0   ;2              
  push r0  ;2               рассчитано ДЛЯ 20МГц!!!!!!
  pop r0   ;2               
  push r0  ;2              
  pop r0   ;2              
  ret      ;4               = 20 тактов (1 микросекунда)
;-------------------------------------------------------------------------------
delay10us:
; Задержка в 10 микросекунд (основана на delay1us) - повышенной точности!      
;                    + 3
  push  wiretemp     ; 2
  ldi  wiretemp, 9   ; 1     << для 20МГц!!! 
  d_loop:            ;                        
  rcall  delay1us    ; 8 
  dec  wiretemp      ; 1 
  brne  d_loop       ; 2/1 
  pop  wiretemp      ; 2  
  nop                ; 1  
  nop                ; 1 
  nop                ; 1 
  ret                ; 4 
;-------------------------------------------------------------------------------
; задержка в wiretemp десятков микросекунд - повышенной точности не требуется
; вход: WireTemp = число десятков микросекунд для задержки (регистр портится)
;-------------------------------------------------------------------------------
delayus:
  dec wiretemp
delayus1:
  rcall delay10us
  dec wiretemp
  brne delayus1
  rcall delay1us
  rcall delay1us
  rcall delay1us
  rjmp delay1us
;-------------------------------------------------------------------------------
; выполняет выдачу сброса в линию 1-wire и возврат состояния PRESENCE
; вход: ничего
; выход: флаг Z установлен, если был PRESENCE
; так как длительность RESET может быть любой, прерывания не запрещаются, 
; если это не необходимо
;-------------------------------------------------------------------------------
reset1w:
  wire1
  sbis wirepin,wirebit            ; проверим наличие 1 в линии
  rjmp presence_fault             ; если нет - это ошибка
  wire0                           ; давим линию в 0
  ldi wiretemp,49
  rcall delayus                   ; 480 микросекунд задержка
  wire1                           ; линию в 1
  ldi wiretemp,6
  rcall delayus                   ; 60 микросекунд задержка
; начинаем ждать PRESENCE
  ldi wiretemp,250                ; ждем с запасом
rw1_wait:
  sbis wirepin,wirebit
  rjmp presence_ok
  rcall delay1us
  dec wiretemp
  brne rw1_wait
presence_fault:
; сюда мы попадаем, если не дождались PRESENCE
  clz                             ; сбрасываем Z-флаг
  ret
presence_ok:
  ; PRESENCE получен
  sez
  ldi wiretemp,49
  rcall delayus
  ret                             ; Z-флаг и так стоит
;-------------------------------------------------------------------------------
; выполняет прием байта из линии
; вход: ничего
; выход: r0 - принятый байт
;-------------------------------------------------------------------------------
resive1w:
  ser wiretemp
  mov r0,wiretemp
;-------------------------------------------------------------------------------
; выполняет передачу байта в линию
; вход: R0 - выводимый байт
; выход: R0 - то, что удалось ВВЕСТИ из линии 
; портит: R0
; примечание: если делать ВЫВОД 0хFF, то на выходе будет ПРИНЯТЫЙ байт
;-------------------------------------------------------------------------------
send1w:
  ldi wiretemp,8                  ; число битов в байте (надо же :) )

sw1_next:                         ; сохраним флаги, 
  pushf                           ; т.к. будем запрещать прерывания
  cli                             ; запрещаем прерывания
  wire0                           ; давим линию в 0
  rcall delay1us                  ; 1 мкс задержки
  ror r0                          ; выталкиваем выводимый бит
  brcc s0                         ; если бит C = 0 - обход 
  wire1                           ; линию в 1
s0:
  push wiretemp
  ldi  wiretemp,9                 ; в некоторых случаях может потребоваться
                                  ; увеличить это значение, но не более 13!
sw1_wait:
  rcall delay1us
  dec wiretemp
  brne sw1_wait
  clc  
  sbic wirepin,wirebit
  sec
  ror wireres
  ldi wiretemp,9
  rcall delayus                   ; 90 микросекунд - длительность тайм-слота
  wire1  
  pop wiretemp
  popf
  dec wiretemp
  brne sw1_next    
  mov r0,wireres
  ret  
;-------------------------------------------------------------------------------
; считывает 9 байтов в буфер, подсчитывает CRC
; портит r0 и SREG, регистры X и Z
;-------------------------------------------------------------------------------
readbytes1w:
  clr wiretemp
  sts CRC,wiretemp                ; обнуляем CRC
  ldiX Buffer
  ldi wiretemp,9
r1w_next:
  push wiretemp
  rcall resive1w                  ; считываем 1 байт
  ; r0=считанному байту, начинаем подсчет CRC
  st X+,r0                        ; сохраняем принятый байт
  rcall crc8                      ; считаем контрольную сумму
  pop wiretemp
  dec wiretemp
  brne r1w_next
  ret
;-------------------------------------------------------------------------------
;  выполняет подсчет CRC по алгоритму 1-Wire
;  вход: r0 - считанный байт
;  выход: CRC - содержит подсчитанную сумму
;  портит: регистр Z
;  примечание: перед первым вызовом CRC необходимо обнулить
;-------------------------------------------------------------------------------
crc8:
  push r0
  ldi wiretemp,8
  mov wireres,wiretemp
r1w_loop_crc:
  lds wiretemp,CRC
  eor r0,wiretemp
  ror r0
  mov r0,wiretemp
  brcc zero
  ldi wiretemp,0x18
  eor r0,wiretemp
zero:
  ror r0
  sts CRC,r0
  pop r0
  ; 4 следующие команды делают циклический сдвиг r0
  push r0
  ror r0
  pop r0
  ror r0
  ; сдвиг закончен - очень удобно, не правда ли?!
  push r0
  dec wireres
  brne r1w_loop_crc
  pop r0
  lds r0,CRC
ret
;-------------------------------------------------------------------------------
; Выбор датчика. Ссылка на массив с уникальным ID в Z
;-------------------------------------------------------------------------------
sel_sensor:
  Send_1w CMD_MATCH_ROM           ; Обращение к конкретному устройству
  ldi r16,8
  ss01:
    lpm r0,Z+
    rcall Send1w
    dec r16
    brne ss01
ret

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

Где три провода, там и четыре, а где четыре — там и i2c или rs-485, без велосипедов.
Я по подобному принципу лет 15 назад светодиод на выключатель освещения в квартире цеплял :)
А зачем вы шунтируете кнопкой и диод и резистор? Может только диод?
смысл в том, чтобы пересилить выход порта и притянуть его к нулю, и это притягивание заметил МК. Если просто закоротить диод, то резистор не позволит этого сделать — просто чуть увеличится выходной ток.
а почему бы не инвертировать режим работы вывода (т.е. переключить выход на вход) на те самые тестовые 20мс? и «перетягивать» ничего не придется
не получится — так как светодиод с резистором и так притянут вход к нулю, даже если включить внутренний pull-up — так как сопротивление pull-up'а на два-три порядка больше, чем гасящего резистора — в итоге, на нем почти ничего не упадет, плюс светодиод под микротоком (ну допустим, 1 вольт) — и МК не почувствует разницы между закороченным и свободным светодиодом — оба уровня будут ниже входного порога
на АЦП конечно да, только использовать каналы АЦП — роскошь для такого простого применения, мне кажется. Я тоже сначала думал сделать на АЦП или на каналах-компараторах — но решение на обычных портах ВВ имхо гораздо более универсальное.
можно, конечно, сместить диапазон delta-U при замкнутом и разомкнутом светодиоде так, чтобы он находился посередине порога переключения, например, включив в земляной провод 2-3 диода в прямом направлении.
Но, во-первых, это лишние элементы, во-вторых из монтажных соображений удобно, когда один из концов кнопки сидит на земле (корпусе), в третьих — помехозащищенность метода будет существенно хуже — смещение цифровой земли всего на 0.5 вольта (в начале статьи я упомянул про применение в автомобиле) сделает схему неработоспособной
У Maxim есть DS2413, микросхема с 2 вводами-выводами, работающая по тому самому 1-Wire.

Используется, например, в Эппловском разъёме MagSafe, где управляет 2 светодиодами. Стоит чуть больше доллара оптом.
У автора не 1-Wire, а «1-Wire», т.е. один провод. Всем известный протокол тут не при чём.
Именно. И у Maxim, создателя настоящего 1-Wire, есть микросхема, выполняющая функции, которые нужны автору.

При этом — все преимущества 1-Wire — готовые библиотеки, шина для нескольких устройств с авто-адресацией и, конечно, надёжность. Это всё оттестировано до нас и работает.
А еще одного провода для собственного питания DS2413 часом не требует? ;)
Нет, там паразитное питание через шину данных. В datasheet пишут, что может давать на нагрузку ток в 20 мА
Это прекрасно, а сам светодиод питать тоже паразиткой с шины? Чип-то получит команду на его включение, а кто даст энергию ему гореть? Или 1-wire переживет шунтирование светодиодом с резистором? ;)
Немного тока с неё взять получится, но, говорят, мало. Единицы милиампер и 5 вольт. На самом деле, вообще никакой конкретной информации нет.

Можно взять напряжение для нагрузки на месте (всё-таки это автомобиль) — но это не так интересно.

(не заметил, что там всего лишь открытый сток)
Ага, примерно так :)

Проблема высосана из пальца, извините
Вот код для дуни:
int state = 3; // просто индикатор состояния кнопки
int one_wire = 5; //"1 вайр"

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(state, OUTPUT);
  pinMode(one_wire, OUTPUT);
  digitalWrite(one_wire, LOW);
}

// the loop routine runs over and over again forever:
void loop() {
  pinMode(one_wire, INPUT);
  digitalWrite(state, !digitalRead(one_wire));
  pinMode(one_wire, OUTPUT);
  delay(20);
}

Симулятор: 123d.circuits.io/circuits/851507-pb-led
Не извиняю — посчитайте количество проводов, связывающих кнопку-индикатор с МК системой в вашем случае
ээээ, 1?
Хочешь сказать, три? В твоем тогда два. В чем проблема цапануть +12В под приборкой для постоянной индикации без всяких выкрутасов?
В чем проблема цапануть +12В под приборкой для постоянной индикации без всяких выкрутасов?

Только вот надо +5, а не +12.
Так надо, чтобы подсветка всегда работала или время от времени? Если всегда, то хоть 220. А если время от времени, то моя схема не пойдет — подсветка будет гореть всегда, когда кнопка нажата.
Так в том и смысл — подсветка должна от МК управляться. В частности, кнопка нормально разомкнута (без фиксации), а подсветка зажигается электроникой. Такое решение позволит, например, помигать ей в некоторых ситуациях, или погасить автоматически при каком-то событии.
Можно узнать модель кнопки. Спасибо.
Последнюю схему не понял. Как при одном входе понять, какая кнопка нажата?
Сканировать по очереди, например.
Но если кнопок много, то и линий много, проще коммутатор сделать и передавать уже настоящей 1-wire
Так а что сканировать по очереди, если физический вход один? Например, что мы получим в случае, если нажато несколько кнопок одновеременно?
Вход один, выходы разные. В каждый конкретный момент времени работает только один выход, и вход знает, с каким выходом сейчас работает. И так по кругу с высокой частотой.
так кнопка, судя по рисунку, вход прямо на землю роняет. При нажатии любой из кнопок у нас на входе земля независимо от состояния выходов. Верно?
А, ну да.
Вообще, в этом случае непонятно, зачем там вход. Можно же с каждой кнопкой работать по отдельности как в первой схеме.
Ха… все выходные не мог дочитать статью до конца, а особенно комментарии…
Товарищи! Вы где усыпили своего инженера?
Не надо ничего замыкать! Подключите кнопкой параллельно светодиоду и резистору… конденсатор! Он не шунтирует цепь, по крайней мере надолго, и если ограничить ток его заряда резистором в 100 Ом он вообще не будет создавать нагрузку порту и мешать светодиоду. Зато его наличие легко определяется по инерционности — когда светодиод включен, короткое отключение порта в режим входа и через определенное время смотрим — есть напряжение, значит кнопка замкнута нет напряжения — кнопка разомкнута.
Если светодиод погашен — выдаем короткий импульс «1» по окончанию импульса через несколько микросекунд смотрим — есть напряжение(паразитная емкость быстро зарядится, но будет держать заряд еще считанные микросекунды) значит кнопка разомкнута, если зарядится не успеет — копка замкнута и подключен значительно больший конденсатор, которому не хватило времени чтобы зарядится.

Немного усложнит опрос кнопки но… преимущества на лицо.
Да, динамикой можно красиво решить задачу — однако суть моей идеи в том, что в месте установки кнопки не нужно никаких дополнительных элементов вообще — так как гасящий резистор уже есть внутри кнопки. Массовый провод подкладывается под гайку крепления, и в МК систему идет всего один провод, а все остальное делается чисто программно. Долгого шунтирования же цепи не будет, т.к. алгоритм обработки нажатия, увидев первое, переведет выходной порт в 0, с короткими 1 только на время очередного опроса. Я вижу существенное преимущество вашего решения только в следующем (помимо того, что оно, конечно, красивое) — в возможности выполнять индикацию от МК системы в то время, пока кнопка нажата — если это в силу каких-то причин необходимо, то стоит выбрать его

И чтобы не писать несколько ответов — кнопки такие продаются на aliexpress.com, а вариант схемы с одним входом, развязанном диодами, конечно, работать не будет — это я загнул. Нужно будет использовать первый или второй вариант

BTW, некоторые кнопки имеют НЗ контакты (но они вроде как дороже, чем НР) — их можно включить последовательно со светодиодом/резистором, и проверять порт в режиме чтения на 1

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории