Преобразование типов

IgorU
Offline
Зарегистрирован: 03.12.2014

Считываю с цифровых портов значения в массив символов Char[], далее нужно преобразовать массив в двоичное число. Будет ли работать правильно оператор преобразования типов Byte(Char[])?

Как правильно выполнить данное действие???

 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

А что Вы понимаете под выражением "преобразовать массив в двоичное число"? Можете привести пример массива и какое число должно в итоге получиться?

IgorU
Offline
Зарегистрирован: 03.12.2014

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

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015
void setup() {
  Serial.begin(9600);
}

void loop() {

  String s = "101101";
  uint32_t n = 0; 
  Serial.print(s);
  
  for (int i=s.length()-1; i>=0 ; i--) {
    if (s[i] == '1') n |= 1<<i;  
  }
  
  Serial.print(" = ");
  Serial.println(n);
  delay(5000);
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

Перибираем строку по одному элементу с права на лево с помощью n. Если текущий символ =0 ничего не делаем. Если единица, то i|=1<<n;. Кончатся символы i будет содержать требуемое число.  

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

И какова максимальная длина Вашего массива?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

IgorU пишет:

Будет ли работать правильно оператор преобразования типов Byte(Char[])?

Оператор ВСЕГДА будет работать правильно (случай аппаратной неисправности МК не рассматриваем).

Другое дело, сумеете ли Вы его правильно применить в своей программе.

IgorU
Offline
Зарегистрирован: 03.12.2014

Еще раз о задаче. Имеется 24 датчика, которые прикреплены на порты, там дискретные значения либо 0 либо 1. (Тренажер)

Задумка - это будет 24-разрядный двоичный код, если с первого по последний порт записать последовательно в строку состояние каждого. Далее этот двоичный код(строку) преобразовать в удобочитаемое число(расшифровка ответа). Вот я и задал вопрос, как правильно сделать преобразование. Может есть изящный способ без посредников(без лишних действий) получить результат.

andriano пишет:
Оператор ВСЕГДА будет работать правильно ...

Другое дело, сумеете ли Вы его правильно применить в своей программе.

Вот по этому поводу и прошу помощи знатоков!

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

IgorU, зачем вы вообще делаете массивы, строки? В одну переменную unsigned long уместятся все ваши 24 бита. Почитайте про битовые операции -это легко и удобно.

IgorU
Offline
Зарегистрирован: 03.12.2014

Я не знаю как сделать, поэтому одна из версий получить результат у меня такая как описал. 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Вам вообще не нужен никакой массив и никакое преобразование. Записываете объединение (union), состоящее из длиного целого и 24-х битовых полей (см.). Складываете свои датчики в битовые поля, а в целом у Вас всегда находится готовое целое число. Ничего не надо никуда преобразовывать.

IgorU
Offline
Зарегистрирован: 03.12.2014

Для новичка сложновато... После объявления объединения из двух полей, как заполнить структуру? Это будет простое присвоение значений каждому байту в структуре? Обращаться к байтам для присвоения (по аналогии) также, как к элементам массива?

Без примера кода пустой звук...  :)

reticular
Offline
Зарегистрирован: 09.06.2016

про прямое обращение к портам почитайте http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry

там и примеры есть

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

IgorU пишет:

как заполнить структуру? Это будет простое присвоение значений каждому байту в структуре?

Биту, а не байту. Просто обращение по имени

IgorU пишет:

Без примера кода пустой звук...  :)

А что, по той ссылке, что я дал, мало примеров? Ну, если мало, теперь Вы знаете слова "union" и "битовые поля" - в гугле не забанили? Примеров в сети чуть ли не больше, чем порнухи.

 

 

IgorU
Offline
Зарегистрирован: 03.12.2014

Спасибо, конечно обращение к битам (оЧепятка). Примеров не мало, просто некоторые конструкции СИ не работают в среде Ардуино,  ранее были попытки неудачные в применении "один к одному".... Возможно по неопытности... Буду разбираться.

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

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

IgorU пишет:

Для новичка сложновато... После объявления объединения из двух полей, как заполнить структуру? Это будет простое присвоение значений каждому байту в структуре? Обращаться к байтам для присвоения (по аналогии) также, как к элементам массива?

Без примера кода пустой звук...  :)

union Datchiki {
  struct {
      unsigned b0: 1;
      unsigned b1: 1;
      unsigned b2: 1;
      unsigned b3: 1;
      unsigned b4: 1;
      unsigned b5: 1;
      unsigned b6: 1;
      unsigned b7: 1;
      unsigned b8: 1;
      unsigned b9: 1;
      unsigned b10: 1;
      unsigned b11: 1;
      unsigned b12: 1;
      unsigned b13: 1;
      unsigned b14: 1;
      unsigned b15: 1; 
      unsigned b16: 1;       
      unsigned b17: 1;
      unsigned b18: 1;
      unsigned b19: 1;
      unsigned b20: 1;
      unsigned b21: 1;
      unsigned b22: 1;
      unsigned b23: 1;
      unsigned b24: 1;
      unsigned b25: 1;
      unsigned b26: 1;
      unsigned b27: 1;
      unsigned b28: 1;
      unsigned b29: 1;
      unsigned b30: 1;
      unsigned b31: 1;
  } bits ;

  uint32_t value;
};  

Datchiki  D;

void setup() {
  Serial.begin(9600);
  
  D.value = 0;    // Обращение для числа
  D.bits.b2 = 1;  // Обращение для бита
  
  Serial.println(D.value);  
}

void loop() {

}

 

IgorU
Offline
Зарегистрирован: 03.12.2014

xDriver избавил от мытарств, Спасибо! Извилины встают на место. Когда знаешь как - оказывается все просто!

Вопрос: при объявлении структуры, обязательно указывать(заявлять) все 32 бита или достаточно моих 24?

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Дополнит, нет типа из трех байт только 1,2,4.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

IgorU пишет:

просто некоторые конструкции СИ не работают в среде Ардуино

Все работают

IgorU пишет:

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

А кто Вас просит? Описали битовое поле (как Вам коллега уже показал) и присавивайте ему результат digitalRead(), кто Вам не даёт?

Всё там нормально, просто не бойтесь и не выдумывайте несуществующих проблем.

IgorU
Offline
Зарегистрирован: 03.12.2014

Принято! Еще раз благодарю всех за разъяснения.

 

ptr
Offline
Зарегистрирован: 28.05.2016

xDriver пишет:

Дополнит, нет типа из трех байт только 1,2,4.

Утверждение ложно. AVR GCC поддерживает трехбайтные целые числа.

"Signed and unsigned 24-bit integers: __int24 (4.7), __uint24 (4.7)."

https://gcc.gnu.org/wiki/avr-gcc

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ptr пишет:

AVR GCC поддерживает трехбайтные целые числа.

"Signed and unsigned 24-bit integers: __int24 (4.7), __uint24 (4.7)."

https://gcc.gnu.org/wiki/avr-gcc

Поддерживает то оно поддерживает, но не совсем.

Например, Serial.print() не знает, как отображать __int24.

И самое главное (и непонятное) - при замене в промежуточных вычислениях long на __int24 происходит не уменьшение, а увеличение как размера кода, так и количества команд.

Например, замена

int a = b*(long)c/d...

на

int a = b*(_int24)c/d...

приводит к увеличению объема прошивки на 20-30 байт.

IgorU
Offline
Зарегистрирован: 03.12.2014

При выводе значения в порт между переключениями потенциала на пинах разряда(переключение датчиков) отображает неверное значение, причем этих значений может быть любое количество от 1 и более, в каждый момент рразное. Переключаю последовательно 1,2,4,8,16,32,64 Скан с порта:

1
1
1
1
3
3
3
2
2
2
28
20
6
6
6
4
4
4
4
13
12
12
8
8
8
8
48
24
24
17
16
16
16
16
112
96
48
48
32
32
32
32
32
127
127
113
113
96
96
64
64
64
64

union Datchiki { 
  struct {
      unsigned b0: 1;
      unsigned b1: 1;
      unsigned b2: 1;
      unsigned b3: 1;
      unsigned b4: 1;
      unsigned b5: 1;
      unsigned b6: 1;
      unsigned b7: 1;
  } bits ;
  uint8_t value;
}; 

Datchiki  D;

void setup()
{
pinMode(A6,INPUT);
pinMode(A5,INPUT);
pinMode(A4,INPUT);
pinMode(A3,INPUT);
pinMode(A2,INPUT);
pinMode(A1,INPUT);
pinMode(A0,INPUT); 

  Serial.begin(9600);
 
uint8_t binaz()
{ 
if (digitalRead(A6) == HIGH) {D.bits.b6=1;} else {D.bits.b6=0;};
if (digitalRead(A5) == HIGH) {D.bits.b5=1;} else {D.bits.b5=0;};
if (digitalRead(A4) == HIGH) {D.bits.b4=1;} else {D.bits.b4=0;};
if (digitalRead(A3) == HIGH) {D.bits.b3=1;} else {D.bits.b3=0;};
if (digitalRead(A2) == HIGH) {D.bits.b2=1;} else {D.bits.b2=0;};
if (digitalRead(A1) == HIGH) {D.bits.b1=1;} else {D.bits.b1=0;};
if (digitalRead(A0) == HIGH) {D.bits.b0=1;} else {D.bits.b0=0;};
D.bits.b7=0;
return D.value;
}


void loop()   
{
binaz();
Serial.println(D.value);
delay(1000); 
}

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

nik182
Offline
Зарегистрирован: 04.05.2015

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

IgorU
Offline
Зарегистрирован: 03.12.2014

Пробовал с резисторами(1К-100К) и без них, результат тот же... Подключаюсь так:

ptr
Offline
Зарегистрирован: 28.05.2016

Проще использовать

pinMode(..., INPUT_PULLUP);

А датчик вешать на землю. И резистор тогда не нужен будет.

 

Судя по всему, датчиками у Вас являются механические контакты, которые обладают способностью к дребезгу. Если это для Вас критично, то смотрите, например, тут http://arduino.ru/forum/programmirovanie/klass-titanovyi-velosiped-dlya-taktovoi-knopki

 

IgorU
Offline
Зарегистрирован: 03.12.2014

ptr пишет:

Проще использовать pinMode(..., INPUT_PULLUP);

Повешал датчик на землю+INPUT_PULLUP = Этот вариант сработал корректно, даже быстрое переключение без ошибок. Спасибо. Может понадобится кому: https://www.arduino.cc/en/Tutorial/InputPullupSerial

Еще вопрос: Нужно сравнить начение D.value(см.выше в коде) с переменной типа Int - как правильно?

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

IgorU пишет:

Еще вопрос: Нужно сравнить начение D.value(см.выше в коде) с переменной типа Int - как правильно?

Совсем правильно - никак потому что D.value беззнаковое, int - знаковое. А так - сравнивайте на здоровье, кто Вам не даёт int a = 23; if (D.value == a) ...

IgorU
Offline
Зарегистрирован: 03.12.2014

Млин, невнимательность...  Разобрался, ошибки в синтаксисе