LINUX.ORG.RU

Дисковый номеронабиратель и Raspberry Pi 4

 , ,


1

2

Всем доброго времении суток! Есть RPi 4b, а также дисковый номеронабиратель от старого телефона. Я хочу на номеронабирателе набрать цифру и вывести ее на экран. Принцып работы я понимаю, но не знаю как это реализовать на Пайтоне. Я нашел пример такой программы но только для ардуино, вот ссылка: https://iarduino.ru/shop/Expansion-payments/telefonnyy-diskovyy-nomeronabiratel.html Тут же и описан принцып работы.

Заранее спасибо!



Последнее исправление: red2211 (всего исправлений: 1)

Ответ на: комментарий от futurama

Как раз хотел написать что пайтон знаю поверхностно. Сам задумку как это должно работать понимаю, но не знаю как это реализовать.

red2211
() автор топика

Принцып работы я понимаю, но не знаю как это реализовать на Пайтоне

Не понимаешь ты, иначе бы не спрашивал...

А делаешь то же самое:
1) инициализируешь пин в режим чтения on/off
2) в цикле читаешь с задержкой 20мс
3) выявляешь импульсы «вкл/выкл» и считаешь их.

Для начала изучи примеры по работе с кнопкой:
http://wikihandbk.com/wiki/Raspberry_Pi:Примеры/Подключение_кнопки
https://ph0en1x.net/86-raspberry-pi-znakomstvo-s-gpio-perekluchatel-i-svetodi...
https://eax.me/raspberry-pi-gpio/

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

Novator ★★★★★
()

Почему именно на RPI4? Жирно как-то слишком для такой хрени. Я бы даже zero w для такого не использовал. Закажи с али arduino/esp

MaddyDick228
()

Дисковый набиратель по сути просто делает «щелчки» в количестве, равном цифре. Тебе нужно посчитать, сколько импульсов пришло не вход.

Zhbert ★★★★★
()
Ответ на: комментарий от Novator

Принцип я таки понимаю, и читать «щелчки» тоже умею. Вот что у меня пока получилось:

import RPi.GPIO as GPIO

dial = 8 #это пин который разрешает читать щелчки
pulse = 10 #это же сам пин на котором и происходят щелчки

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(dial, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(pulse, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while True:
    print("PULSE: " + str(GPIO.input(pulse)) + " DIAL: " + str(GPIO.input(dial)))

Я не понимаю как мне сделать сам подсчёт количества «щелчков» в коде, а словами я понимаю что должен идти постоянный цикл в нём сначала мы проверяем разрешено ли считывать если да то начинаем читать и записывать сколько раз оно «щёлкнуло» и потом выводим на экран число. Как-то так.

red2211
() автор топика
Ответ на: комментарий от MaddyDick228

Да я знаю что rpi слишком жирно использовать для такого. Но брал ее просто для всякого разного там ретро игрушки поиграть, что-то контролировать по GPIO и тп.

red2211
() автор топика
Ответ на: комментарий от anonymous

Да но опять же это для ардуино а у меня малина.

red2211
() автор топика
Ответ на: комментарий от red2211

Я не понимаю как мне сделать сам подсчёт количества «щелчков» в коде

У тебя же есть код на Си:

    if(!digitalRead(pinDIAL)){                          // Если разрешено чтение импульсов (на синем проводе логический «0»), то ...
        delay(20);                                      // Подавляем дребезг шунтирующей контактной группы.
        cntPULSE=0;                                     // Сбрасываем счётчик.
        while(!digitalRead(pinDIAL)){                   // Входим в цикл, пока на синем проводе не появится логическая «1» ...
            if(digitalRead(pinPULSE)){                  // Если поступил импульс (на жёлтом проводе логическая «1»), то ...
//              Фронт импульса:                         //
                delay(5);                               // Подавляем дребезг импульсной контактной группы.
                while(digitalRead(pinPULSE)){delay(5);} // Ждём завершения импульса.
//              Спад импульса:                          //
                delay(5);                               // Подавляем дребезг импульсной контактной группы.
                cntPULSE++;                             // Увеличиваем счётчик полученных импульсов.
            }                                           //
        }                                               // Выход из цикла while сигнализирует о появлении логической «1» на синем проводе.
        delay(20);                                      // Подавляем дребезг шунтирующей контактной группы.
        if(cntPULSE){                                   // Если был зафиксирован хотя бы 1 импульс, то ...
            if(cntPULSE>=10){cntPULSE=0;}               // Если поступило 10 импульсов, значит набрана цифра 0.
            Serial.println(cntPULSE);                   // Выводим набранную цифру (количество поступивших импульсов).
        }                                               //
    }                                                   //
}             

Перепиши на питоне:

while True:
  if not GPIO.input(dial):
    sleep(0.02)
    cntPULSE=0
    while not GPIO.input(dial):
      if GPIO.input(pulse):
        sleep(0.005)
        while GPIO.input(pulse):
          sleep(0.005)
        sleep(0.005)
        cntPULSE += 1
      sleep(0.005)
    if (cntPULSE>0) and (cntPULSE<10):
      print('Считано импульсов: '+str(cntPULSE))
  else:
    sleep(0.02)

Попробуй.

Novator ★★★★★
()
Последнее исправление: Novator (всего исправлений: 1)
Ответ на: комментарий от red2211

словами я понимаю

Ты прям как собака - всё понимаешь, а сказать не можешь.

понимаю что должен идти постоянный цикл в нём сначала мы проверяем разрешено ли считывать если да то начинаем читать и записывать сколько раз оно «щёлкнуло» и потом выводим на экран число

Ну так а в чём конкретно проблема-то? Не знаешь как в питоне написать цикл? Проверку? Как считывать импульсы? Начни уже есть слона по частям.

no-such-file ★★★★★
()
Ответ на: комментарий от Novator

Я подобный код пытался писать но реакции ноль. Программа запускается и просто пустой рядок я набираю цифру жду и ничего.

red2211
() автор топика
Ответ на: комментарий от red2211

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

Ну а по сути… Я ненастоящий сварщик, но первое, что приходит в голову — а ты уверен, что это не аппаратная проблема? Ты про код пишешь, а про железо ничего. Ты как номеронабиратель к GPIO подключаешь? Схему подключения сам продумывал или где брал? Может, просто контакта нет? :)

hobbit ★★★★★
()
Ответ на: комментарий от red2211

Программа запускается и просто пустой рядок я набираю цифру жду и ничего.

Тогда вот что сделай:
1. Откажись от линии «dial».
2. Убери из кода упоминание «dial».
3. На линию «pulse» параллельно повесь кнопку.
4. Попробуй генерять импульсы кратким нажатием кнопки:

#Допустимые размеры импульсов и пауз в миллисекундах
PulseHiMinMSec = 30
PulseHiMaxMSec = 900
PulseLoMinMSec = 30
PulseLoMaxMSec = 1000

while True:
  #Если есть импульс, начинаем считать
  if GPIO.input(pulse):
    PulseCount = 0
    dialing = True
    while dialing:      
      #Ожидание конца импульса
      timeHi = 0
      while GPIO.input(pulse) and (timeHi<=PulseHiMaxMSec):
        sleep(0.01)  #ждём 10 мс
        timeHi += 10 #добавляем 10 мс в длину импульса
      #Если длина импульса в диапазоне, засчитываем импульс
      if (timeHi>=PulseHiMinMSec) and (timeHi<=PulseHiMaxMSec)
        PulseCount += 1
        #И ждём конца паузы
        timeLo = 0
        while (not GPIO.input(pulse)) and (timeLo<=PulseLoMaxMSec):
          sleep(0.01)
          timeLo += 10  #добавляем 10 мс в длину паузы
        if (timeLo<PulseLoMinMSec) or (timeLo>PulseLoMaxMSec):
          dialing = False
      else:
        dialing = False
    if PulseCount>0:
      print('Считано импульсов: '+str(PulseCount))
  else:
    sleep(0.01)
Novator ★★★★★
()
Ответ на: комментарий от hobbit

Во-первых, посылаю тебе луч добра и желаю успехов, подобные проекты — это всегда хорошо.

Спасибо за поддержку! Схему сам делал. У номеронабирателя есть всего 3 проводка: земля, разрешающий чтение и импульсный. Подключал землю к 14 GPIO, разрешающий к 8 GPIO и импульсный к 10 GPIO. Проблема не в этом так как сделал простую прогу которая читает входы и все есть.

red2211
() автор топика
Ответ на: комментарий от red2211

Я тебе только что выше написал, попробуй.

Novator ★★★★★
()
Ответ на: комментарий от Novator

Я через встроеный в расбиан иде питона сделал дебаг и если вручную медлено крутить номеронабиратель то программа работает!

red2211
() автор топика
Ответ на: комментарий от red2211

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

Какая программа работает? Моя последняя?

Что значит «медленно»? Попробуй уменьшить:

PulseHiMinMSec = 10
PulseLoMinMSec = 10

Наверно там импульсы или паузы короче 30 мс.

Novator ★★★★★
()
Ответ на: комментарий от Novator

Вот эта:

while True:
  if not GPIO.input(dial):
    sleep(0.02)
    cntPULSE=0
    while not GPIO.input(dial):
      if GPIO.input(pulse):
        sleep(0.005)
        while GPIO.input(pulse):
          sleep(0.005)
        sleep(0.005)
        cntPULSE += 1
      sleep(0.005)
    if (cntPULSE>0) and (cntPULSE<10):
      print('Считано импульсов: '+str(cntPULSE))
  else:
    sleep(0.02)

Что значит «медленно»?

Щас запишу видео.

red2211
() автор топика
Ответ на: комментарий от red2211

Вот эта:

Эта старая, я тебе новую программу написал.

Novator ★★★★★
()
Ответ на: комментарий от red2211

Подключал землю к 14 GPIO, разрешающий к 8 GPIO и импульсный к 10 GPIO.

Ещё вот эту херню вначале не забывай ставить:

GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_UP)

у тебя ведь полюбому без резисторов включено.

Novator ★★★★★
()
Ответ на: комментарий от Novator

Ещё вот эту херню вначале не забывай ставить:

Да это не забываю.

Вторая программа работает, но не полностю корректно. Иногда вместо например 9 пишет 1 и 8 и тд.

red2211
() автор топика
Последнее исправление: red2211 (всего исправлений: 1)
Ответ на: комментарий от red2211

Иногда вместо например 9 пишет 1 и 8 и тд.

Тогда ещё верхние границы увеличь:

PulseHiMaxMSec = 1500
PulseLoMaxMSec = 1500

Короче, «поиграй» границами.

Novator ★★★★★
()
Ответ на: комментарий от red2211

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

Как уже выше спросили — что значит «медленно»?

На всякий случай напомню, что в телефонном номеронабирателе имеют значение те импульсы, которые идут после отпускания диска. Человек вставляет палец в дырку, например, над цифрой «6», крутит до рычажка, вынимает палец — и диск самостоятельно возвращается в исходное положение, и делает это с фиксированной скоростью. И программа должна реагировать именно на эти импульсы, идущие во время возврата диска (ЕМНИП, когда диск крутится пальцем, импульсы и не идут, но это не точно).

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

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

(ЕМНИП, когда диск крутится пальцем, импульсы и не идут, но это не точно).

Нет, диск можно крутить пальцем и импульсы будут идти. Проверено мультиметром!

red2211
() автор топика
Ответ на: комментарий от red2211

Огромный минус не использовать разрешающий пин это то что если например делать какой-то например телефон то быстро набрать номер не получится. Сейчас попытался набрать номер телефона и получилось вместо номера просто сумма чисел номера.

red2211
() автор топика
Последнее исправление: red2211 (всего исправлений: 1)
Ответ на: комментарий от red2211

Тогда надо вспоминать, как принимающее устройство отличало «прямые» импульсы от обратных. Ещё раз — АТС подсчитывала именно импульсы при обратном движении.

Кстати, ссылку вот на эту техноняшку уже кидали?

Сейчас попытался набрать номер телефона и получилось вместо номера просто сумма чисел номера.

Ну значит, у тебя просто программа ловит всё подряд. Так-то при нормальном использовании там должны быть хорошо выделяемые серии равномерно идущих импульсов, между которыми - пауза. Быстро номер набирался, я помню.

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 2)
Ответ на: комментарий от hobbit

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

Обратных импульсов нет. Когда крутиш диск то нет импульсов вообще, импульсы идут только когда отпускаешь диск на цифре

red2211
() автор топика
Ответ на: комментарий от red2211

импульсы идут только когда отпускаешь диск на цифре

Ну я так же сначала так и написал! Меня просто смутила формулировка «медленно крутить номеронабиратель». Если он исправен, то скорость подачи импульсов определяет он сам, на неё и надо ориентироваться.

hobbit ★★★★★
()
Ответ на: комментарий от red2211

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

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

Я уже этим занимаюсь сначала пробую первую отладить но если не получится тогда буду дописывать вторую.

red2211
() автор топика
Ответ на: комментарий от red2211

Ну он же не зря сам вторую написал, я бы ориентировался на неё…

hobbit ★★★★★
()
Ответ на: комментарий от red2211

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

pihter ★★★★★
()
Ответ на: комментарий от red2211

Мне далее интересно почему первая программа не работает. Вот видео:

Cкорее всего неправильные задержки, и как следствие, импульсы определяются некорректно.

Вторая программа не требует линии «dial», поэтому имхо она надёжнее. Ну и плюс, во 2й можно точно подобрать размеры импульсов и пауз именно для твоего номеронабирателя.

Novator ★★★★★
()
Ответ на: комментарий от Novator

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

Этим я займусь потом, сначала хочу сделать так чтобы была задействована линия «Dial»

red2211
() автор топика

Ура у меня вышло!!!

Вот код:

import RPi.GPIO as GPIO
from time import sleep

dial = 8
pulse = 10

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(dial, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(pulse, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while True:
    if not GPIO.input(dial):
        sleep(0.02)
        cntPULSE = 0
        while not GPIO.input(dial):
            if (not GPIO.input(pulse)) and (not GPIO.input(dial)):
                sleep(0.005)
                while (not GPIO.input(pulse)) and (not GPIO.input(dial)):
                    sleep(0.005)
                sleep(0.005)
                cntPULSE += 1
        sleep(0.02)
        if cntPULSE:
            if cntPULSE >= 10:
                cntPULSE = 0
            print(cntPULSE)

Думаю можно было написать лучше но есть как есть.

Огромное спасибо за помощь @Novator и @hobbit !

red2211
() автор топика
Ответ на: комментарий от red2211

АТС определяет набор следующей цифры по паузе между импульсами больше 500 мс.
И тебе нужно отделять набор следующей цифры по этой паузе.
Все что меньше этой длительности идет на инкремент текущей цифры.
Если больше - фиксируем текущую цифру и начинаем инкрементировать следующую.

anonymous
()
Ответ на: комментарий от red2211

Да меня-то не надо рядом с ним, он целую программу написал, а я только пару подсказок кинул…

Но хорошо, что получилось.

hobbit ★★★★★
()
Ответ на: комментарий от red2211

Ура у меня вышло!!!
Вот код:

Муть какая-то, ну да ладно - главно работает.
Накрайняк у тебя ещё есть вторая программа :)

Novator ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.