Как перевести статус с 8 пинов в десятичное число?

imv14
Offline
Зарегистрирован: 02.04.2014

Все добрый день. Начал немного разбираться с програмированием Ардуино. Включаю 8 релейный модуль через компьютер, то есть на каждый пин с 3 по 10 подцеплены к релейному модулю(всего 8). Включение и выключение работает.

Хочу после посылки команды с компа на реле получить ответную команду о подтверждение вкл/выкл реле. Опрашиваем 8 пинов, если реле включено, то 1, если выключена, то 0. Всего задействовано 8 ног получается 8 бит - 1 байт(в бинарном представление), надо его перевести в десятичную и послать в порт.   

Помогите пожалуйста.

MaksMS
Offline
Зарегистрирован: 11.03.2013

Состояние всех выводов одного порта можно просто считать из регистров PORTx ,где х -имя порта  ,например PORTB..

Вот понятне может будет http://easyelectronics.ru/avr-uchebnyj-kurs-ustrojstvo-i-rabota-portov-vvoda-vyvoda.html

nick_shl
Offline
Зарегистрирован: 25.03.2014

imv14 пишет:
Хочу после посылки команды с компа на реле получить ответную команду о подтверждение вкл/выкл реле. Опрашиваем 8 пинов, если реле включено, то 1, если выключена, то 0.
Каких пинов? Опрашивать те же к которым подключены реле не имеет смысла.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

почему это не имеет смысла? У меня так и сделано - digitalRead(relayPin[i]) - если там HIGH, то реле включено.

Да, это не 100% однозначность (0,5% что реле может быть неисправно), но лучше чем 50% (либо включено, либо нет  :} )

imv14
Offline
Зарегистрирован: 02.04.2014

MaksMS пишет:

Состояние всех выводов одного порта можно просто считать из регистров PORTx ,где х -имя порта  ,например PORTB..

Вот понятне может будет http://easyelectronics.ru/avr-uchebnyj-kurs-ustrojstvo-i-rabota-portov-vvoda-vyvoda.html

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

imv14
Offline
Зарегистрирован: 02.04.2014

Допустим считаю пин digitalRead(relayPin[i]) в цикле, записываю их в строку или массив, как потом привести к десятичному числу от 0 до 255.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

Вот набросок, но надо проверять

// в начало скетча:

// количество реле
#define RELAY_COUNT 8

// массив с номерами пинов, которые подключены к реле
byte relayPin[RELAY_COUNT] = {7,8,9,10,11,12,3,4};

// "двоичное" представление состояний реле - массив (вкл = 1 / выкл = 0)
boolean pinState[RELAY_COUNT];

// десятичное представление двоичного числа: 00000000=0, 00000001=1, 00000010=3 - классика
byte relayState = 0;


void setup()
{
  Serial.begin(9600);
  for (byte i = 0; i < RELAY_COUNT; i++)
  {
    pinMode(pinRelay[i], OUTPUT);  			  // инициализируем пины для реле как выход
    // digitalWrite(pinRelay[i], LOW);        // принудительно гасим реле (если нужно)
  }
}


// где-то в коде:
for (byte i = 0; i < RELAY_COUNT; i++)		// читаем состояние реле
{
  pinState[i] = digitalRead(relayPin[i]);	 // заносим в массив состояние пинов
  relayState <<= 1;
  relayState |= pinState[i];			    // формируем десятичное представление
}

Serial.print("Relay pins state: ");
Serial.print(pinState); 				// выводим "бинарный" массив состояний
Serial.print("Summary relays state: ");
Serial.print(relayState); 				// выводим число, где закодирован массив состояний

 

leshak
Offline
Зарегистрирован: 29.09.2011
relayState=0; // лучше вначале все сбросить.
for (byte i = 0; i < RELAY_COUNT; i++)       // читаем состояние реле
{
  bitWrite(relayState,i,digitalRead(relayPin[i]));
}

Serial.print("State=");
Serial.print(relayState,DEC); // десятично

Serial.print(", B");
Serial.print(relayState,BIN); // двоично (для проверки, что верно прочитали).

А вообще, тут нужно еще нужно разобратся что за задача такая "нужно перевести в десятичное". Никаких "переводов" в десятичное - не существует. Все всегда хранится двоично. Десятично/двоично/шестнадцатерично - это только уже "для человека". "Вывести в 10-тичном виде".

А если почитать Прямое управления выходами через регистры микроконтроллера Atmega

И повести ноги (для uno/nano и т.п.) на пины с 8-го, по 13-тый, то "прочитать состояние 8-ми ног и вывести десятично в Serial" можно вообще одной строкой.

Serial.println(PINB,DEC); // DEC - можно опустить, оно так, для наглядности

 

imv14
Offline
Зарегистрирован: 02.04.2014

Большое спасибо, вечером попробую. Результат сообщу.

leshak
Offline
Зарегистрирован: 29.09.2011

leshak пишет:

И повести ноги (для uno/nano и т.п.) на пины с 8-го, по 13-тый, то "прочитать состояние 8-ми ног и вывести десятично в Serial" можно вообще одной строкой.
Serial.println(PINB,DEC); // DEC - можно опустить, оно так, для наглядности

Хотя нет. 8-13 это шесть ног. Прийдется тогда два порта использовать (На PORTB PB6,PB7 - заняты под резонатор).

Тогда как-то так должно быть.

Serial.println(  ((PIND | B11000000) & (PINB | B00111111)),DEC);

 Так прочитаем ноги от D6 до D13.

imv14
Offline
Зарегистрирован: 02.04.2014


#define RELAY_COUNT 8                              // количество реле
byte relayPin[RELAY_COUNT] = {2,3,4,5,6,7,8,9}; // количество реле
boolean pinState[RELAY_COUNT];                     // "двоичное" представление состояний реле - массив (вкл = 1 / выкл = 0)
byte relayState = 0;                               // десятичное представление двоичного числа
 
 
//SoftwareSerial mySerial(11, 10); // Пины для RX, TX 
int Rele = 0;
 
void setup() {
  Serial.begin(9600); 
    for (int thisPin = 2; thisPin < 10; thisPin++) {
      pinMode(thisPin, OUTPUT);
        digitalWrite(thisPin, HIGH);
      } 
}
void loop() {
  if (Serial.available() > 0) {
    Rele = Serial.read();
    switch (Rele) {
    case 1:    
      digitalWrite(2, HIGH);
      break;
    case 17:    
      digitalWrite(2, LOW);
      break;
    case 2:    
      digitalWrite(3, HIGH);
      break;
    case 18:    
      digitalWrite(3, LOW);
      break;
    case 3:    
      digitalWrite(4, HIGH);
      break;
    case 19:    
      digitalWrite(4, LOW);
      break; 
    case 4:    
      digitalWrite(5, HIGH);
      break;   
    case 20:    
      digitalWrite(5, LOW);
      break; 
    case 5:    
      digitalWrite(6, HIGH);
      break;
    case 21:    
      digitalWrite(6, LOW);
      break;
    case 6:    
      digitalWrite(7, HIGH);
      break;
    case 22:    
      digitalWrite(7, LOW);
      break;
    case 7:    
      digitalWrite(8, HIGH);
      break;
    case 23:    
      digitalWrite(8, LOW);
      break; 
    case 8:    
      digitalWrite(9, HIGH);
      break;   
    case 24:    
      digitalWrite(9, LOW);
      break; 
    default:
    break;           
    }   
  }
// Выводим состояние реле
 // relayState=0; // лучше вначале все сбросить.
  for (byte i = 0; i < RELAY_COUNT; i++)       // читаем состояние реле
{
  bitWrite(relayState,i,digitalRead(relayPin[i]));
}
  Serial.print(relayState,DEC); // десятично
  Serial.print(", B");
  Serial.println(relayState,BIN); // двоично (для проверки, что верно прочитали).
  delay(1000);
}
imv14
Offline
Зарегистрирован: 02.04.2014

Научите правильно вставлять код программы. Вот так написал. Почему то у меня изночально реле находится в состояние выключено, а показывает 11111111 (вкл.). Может я как-то покорректней написать вкл/выкл реле не через case. 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

imv14 пишет:
Почему то у меня изночально реле находится в состояние выключено, а показывает 11111111 (вкл.).
потому что в setup ты его включаешь: digitalWrite(thisPin, HIGH);
Либо оно у тебя инвертированное - при отсутствии сигнала открыто, а при наличии питания закрыто.

Switch сократить можно, но тогда надо определиться с командами, которые ты будешь вводить: сейчас команда для одного реле, причём на включение и выключение раздельные. Можно упростить: повторная команда на тот же адрес (например "3") выключает реле.
Можно реализовать по другому: команда - это двузначное число: первый разряд - номер реле, второй - действие, т.е. "31" - это включить 3-е реле, "50" - это выключить 5-е реле.
Можно реализовать так, что управлять - можно сразу всеми реле через бинарную восьмизнаковую команду ("00100100" -включить 3 и 6 реле) или через десятичную команду ("70" = 01000110- включить 2, 3 и 7 реле, отсчёт справа налево).

imv14
Offline
Зарегистрирован: 02.04.2014

Спасибо, оставлю пока как есть.