Grabduck

Как я собрал первый аналоговый клиент для твиттера

:

Однажды у нас с друзьями появилась идея, почему бы не сделать так, чтобы на старом дисковом телефоне можно было набрать какое-то сообщение и отправить его. А и правда, подумал я, тем более мне давно хотелось сделать что-нибудь на базе Arduino, ведь платформа доступная и простая в изучении. Да и идея с вдыханием новой жизни в винтажный телефонный аппарат показалась привлекательной. В результате получился Tweephone.

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


Чтобы была возможность набирать символы, я выбрал принцип набора текста на мобильниках с 12-ти кнопочной клавиатурой. Например, чтобы набрать букву «a» нужно провернуть двойку один раз, а для буквы «f» — тройку три раза.

Недолго думая, я организовал среди друзей поиск собственно самого аппарата (который был найден у бабушки моего приятеля), достал Arduino и LCD экран 16*2 строчек, паяльные принадлежности, свободное время, ну и острое желание сделать что-то руками.

Заполучив Arduino, я сразу подключил к нему LCD, покрутил тестовые примеры для светодиодов, кнопок и LCD экрана. Найти их можно на сайте Arduino.

Сняв крышку корпуса телефона и изучив внутренности, я обнаружил, что работа самого номеронаберателя очень проста: он имеет 3 контакта, один из которых замыкается с двумя другими. С первым — в случае, когда диск прокручивается, а со вторым — по умолчанию замкнут, но в процессе того, как диск возвращается в исходное состояние, размыкается определенное количество раз, в зависимости от номера, относительно которого диск начинал движение. Это всё было видно невооруженным взглядом, но дополнительно убедиться в правильности работы можно используя мультиметр, который пищит при коротком замыкании контактов. Также стало понятно, что состояние “трубка на аппарате”/”трубка снята” тоже можно использовать программно, потому что это действие попросту замыкает-размыкает контакты кнопки на плате телефона.

Учитывая эти знания, стало понятно, что грубо говоря, я имею дело с 3-мя кнопками, данные с которых нужно считывать программно, а всё остальное — дело алгоритма. Поэтому каждую из них я подключил по схеме с сайта к digital-портам Arduino, и собрал всё это дело на макетной плате.

Осталось открыть среду разработки и написать код, который бы считывал импульсы с digital-портов, преобразовывал их в символы и отправлял в твиттер. Так как плат коммуникаций для Arduino под рукой не оказалось, то решено было подключать телефон по USB компьютеру, на котором запущен скрипт, который считывает строки из Serial-порта Arduino и постит их.

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

Во-первых, чтобы работать с digital-портом, нужно указать, каков режим этого порта при инициализации:

const unsigned int diskState = 7;
const unsigned int diskCounter = 8;

void setup() {
pinMode(diskState, INPUT);
pinMode(diskCounter, INPUT);
}

Как видно из листинга, я использовал 7 и 8 порты для подключения непосредственно номеронабирателя.

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

unsigned int prevDiskCountState = HIGH;

void loop() {
unsigned int currDiskState = digitalRead(diskState);
unsigned int currDiskCountState = digitalRead(diskCounter);
if(currDiskState == HIGH) {
if(prevDiskCountState == HIGH && currDiskCountState == LOW) {
currDiskCount++;
delay(100);
}
prevDiskCountState = currDiskCountState;
}else{
if(currDiskCount > 0) {
// обработка набранной цифры
}
}
}

Такая же проверка осуществляется для статуса телефонной трубки, и в случае, если есть текст и трубку положили, выполняется запись строки в Serial порт.

Serial.println(msg);

А на компьютере запущен небольшой Ruby-скрипт, который считывает строку и отправляет ее в твиттер.

<br/>require "serialport"<br/>require "twitter"<br/> <br/># params for serial port<br/>port_str = "/dev/tty.usbserial-A900cdNp"<br/>baud_rate = 9600<br/>data_bits = 8<br/>stop_bits = 1<br/>parity = SerialPort::NONE<br/> <br/>sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)<br/> <br/># twitter auth<br/>require './Config.rb'<br/>Twitter.configure do |config|<br/>  config.consumer_key = YOUR_CONSUMER_KEY<br/>  config.consumer_secret = YOUR_CONSUMER_SECRET<br/>  config.oauth_token = YOUR_OAUTH_TOKEN<br/>  config.oauth_token_secret = YOUR_OAUTH_TOKEN_SECRET<br/>end<br/> <br/>client = Twitter::Client.new<br/> <br/>while true do<br/>  line = sp.gets<br/>  if line<br/>    puts line<br/>    client.update(line)<br/>  end<br/>end<br/> <br/>sp.close <br/>

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

Весь код проекта доступен на GitHub, поэтому каждый может разобраться в деталях и реализовать что-нибуть похожее.
Твит для ХабраХабра
Твиттер проекта
Страница проекта

Пишите, если есть вопросы.