Подскажите по преобразованию данных

treur
Offline
Зарегистрирован: 18.10.2015

Собственно проблема такая -

читаюсообщение с CANBUS, к примеру 01 FF 00 00 00 00 00 00 необходимо получить результат вида 01FF и перевести в десятичную систему т.е. 511, если во втором числе всё, что угодно кроме FF, то преобразуется правильно, как только FF - затык. Код ниже, что я делаю не так?

#include <mcp_can.h>
#include <SPI.h>

long unsigned rxId;
long previousMillis = 0;
unsigned char len = 0;
unsigned char rxBuf[8];
int value = LOW;
long freq = 0;
long b;
long input;
MCP_CAN CAN(10);
void setup() {
  CAN.begin(CAN_500KBPS);

}

void loop() {
 canread();
      if (rxId == 0x37E && (len == 5 || len == 6 || len == 7)) {
        goto a39;
      }
a39:
  canread();
  if (rxId == 0x37E) {
    input =  uint16_t(rxBuf[0] << 7 | rxBuf[1] );
  }
  blink(input);
  goto a39;
}

void blink (long input)
{
  if (b != input)
  {
    b = input;
  }
  if (input > 0)
  {
    freq = 65535 / b;
    if (millis() - previousMillis > freq) {
      previousMillis = millis();
      if (value == LOW)
        value = HIGH;
      else
        value = LOW;
      digitalWrite(3, value);
    }
  }
  else if (input == 0)
  {
    digitalWrite(3, HIGH);
  }
}

void canread()
{
  CAN.readMsgBuf(&len, rxBuf);
  rxId = CAN.getCanId();
}

 

_kp
Offline
Зарегистрирован: 07.10.2016

Используйте для беззнаковых величин unsigned int, unsigned long, uint16_t и т.п.
Иначе при обработке значений больше 0x80, 0x8000, 0x80000000 получим неверный результат.

В приведенном фрагменте кода, знаковые переменые  не требуются, заменяйте все int на unsigned, а long на unsigned long.

treur
Offline
Зарегистрирован: 18.10.2015

после замены ровно тот же результат - 01FF=00FF

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

Интересно, что Вы хотели здесь сделать?

void loop() {

 canread();
      if (rxId == 0x37E && (len == 5 || len == 6 || len == 7)) {
        goto a39;
      }
a39:
  canread();
  if (rxId == 0x37E) {
    input =  uint16_t(rxBuf[0] << 7 | rxBuf[1] );
  }
  blink(input);
  goto a39;
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
 // a что такая конструкция делает?
input =  uint16_t(rxBuf[0] << 7 | rxBuf[1] );
// может надо так
input =  (uint16_t)rxBuf[0] << 7 | rxBuf[1] ;
// или так
input =  (int)(rxBuf[0] << 7 | rxBuf[1] ;

 

treur
Offline
Зарегистрирован: 18.10.2015

andriano пишет:

Интересно, что Вы хотели здесь сделать?

void loop() {

 canread();
      if (rxId == 0x37E && (len == 5 || len == 6 || len == 7)) {
        goto a39;
      }
a39:
  canread();
  if (rxId == 0x37E) {
    input =  uint16_t(rxBuf[0] << 7 | rxBuf[1] );
  }
  blink(input);
  goto a39;
}

 

1. Определить авто по уникальному ID (код сильно кастрирован ибо идентификаторы - военная тайна)

2. Прочитать 2 бита из 8

3. Моргнуть светодиодом через функцию blink

4. Вернуться в цикл а39.

treur
Offline
Зарегистрирован: 18.10.2015

qwone пишет:

 // a что такая конструкция делает?
input =  uint16_t(rxBuf[0] << 7 | rxBuf[1] );
// может надо так
input =  (uint16_t)rxBuf[0] << 7 | rxBuf[1] ;
// или так
input =  (int)(rxBuf[0] << 7 | rxBuf[1] ;

 

Оказалось что надо так -

input =  uint16_t(rxBuf[0] << 8 | rxBuf[1] );

treur
Offline
Зарегистрирован: 18.10.2015

В общем немного переписал, но грабли остались, поможите люди добрые бьюсь как лбом об стену - не преобразуется из 16 в 10ку input хоть лопни.

#include <mcp_can.h>
#include <SPI.h>

unsigned char len = 0, rxBuf[8];
unsigned kbps = 0, value = LOW;
unsigned long rxId, input, freq = 0, previousMillis = 0;

MCP_CAN CAN(10);
void setup() {
  CAN.begin(CAN_500KBPS);

}

void loop() {
 canread();
      if (rxId == 0x37E && len == 7) {
        goto a39;
      }
a39:
  canread();
  if (rxId == 0x37E) {
    input =  uint16_t(rxBuf[0] << 8 | rxBuf[1] );
  }
  blink(input);
  goto a39;
}

void blink (unsigned int input)
{
  canread();
  if (input != 0)
  {
    freq = 65535 - input;

    if (millis() - previousMillis > freq) {
      previousMillis = millis();
      value = !value;
      digitalWrite(3, value);
    }
  }
  else if (input == 0)
  {
    digitalWrite(3, HIGH);
  }
}

void canread()
{
  CAN.readMsgBuf(&len, rxBuf);
  rxId = CAN.getCanId();
}

 

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

treur пишет:

1. Определить авто по уникальному ID (код сильно кастрирован ибо идентификаторы - военная тайна)

2. Прочитать 2 бита из 8

3. Моргнуть светодиодом через функцию blink

4. Вернуться в цикл а39.

1 - понятно.

2 - понятно, только наверное 2 байта

3 - не понятно, носудя по коду моргнуть светодиодом на время 65535 минус то что прочитали 0x01FF (511) миллисек, то есть на 65024  миллисек (65 сек = чуть больше минуты), так ?

4 - код ужасный, это не надо.

более развернуто опишите.

а по поводу ваших мытарств с input, вот попробуйте, пытался по шагам


void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);

  byte b1=0x01,b2=0xFE;
  
  unsigned long input = b1;

  
  Serial.print("input = ");
  Serial.println(input,HEX);
  
  input <<= 8;
  Serial.print("input = ");
  Serial.println(input,HEX);
  
  input |= b2;
  Serial.print("input = ");
  Serial.println(input,HEX);  

  Serial.print("input = ");
  Serial.println(input); 
}

void loop() {
}

 

treur
Offline
Зарегистрирован: 18.10.2015

xDriver пишет:

treur пишет:

1. Определить авто по уникальному ID (код сильно кастрирован ибо идентификаторы - военная тайна)

2. Прочитать 2 бита из 8

3. Моргнуть светодиодом через функцию blink

4. Вернуться в цикл а39.

1 - понятно.

2 - понятно, только наверное 2 байта

3 - не понятно, носудя по коду моргнуть светодиодом на время 65535 минус то что прочитали 0x01FF (511) миллисек, то есть на 65024  миллисек (65 сек = чуть больше минуты), так ?

4 - код ужасный, это не надо.

более развернуто опишите.

а по поводу ваших мытарств с input, вот попробуйте, пытался по шагам


void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);

  byte b1=0x01,b2=0xFE;
  
  unsigned long input = b1;

  
  Serial.print("input = ");
  Serial.println(input,HEX);
  
  input <<= 8;
  Serial.print("input = ");
  Serial.println(input,HEX);
  
  input |= b2;
  Serial.print("input = ");
  Serial.println(input,HEX);  

  Serial.print("input = ");
  Serial.println(input); 
}

void loop() {
}

По 4му пункту - прошу пардона, ну не кодер я, немного на PHP пишу...... не суть. Плюс здесь просто кусок из контекста - циклов типа "а39" в полной версии около 200.

Попробую более развернуто - надо на выхлопе получить меандр с D3 что то примерно около 600 импульов в минуту, частота меандра естественно должна повышаться по увеличению первых 2х байт сообщения с CAN шины.

Как то так.

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

посмотрите вот это http://arduino.ru/forum/proekty/generator-s-reguliruemoei-chastotoi-na-arduino

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

treur
Offline
Зарегистрирован: 18.10.2015

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