ARDUINO Вопрос по преобразованию uint32_t в uint16_t

mir0tv0rec

✩✩✩✩✩✩✩
14 Янв 2019
24
0
Доброго дня! Подскажите, как преобразовать/присвоить значение переменной типа unsigned long (uint32_t), переменной типа uint16_t. При этом значения 4 байтной переменной не превышают диапазон 2 байтной.

C++:
uint16_t curLSB, rSh, calValue;

uint32_t tmpVal = (uint32_t) rSh * curLSB;    // curLSB = 203, rSh = 1773
Serial.print("tmpVal = "); Serial.println(tmpVal);    // tmpVal = 359919 - тут правильно
tmpVal = 512000000 / tmpVal;                         
Serial.print("tmpVal = "); Serial.println(tmpVal);    // tmpVal = 1422 - тут тоже
calValue = (uint16_t)(tmpVal));
Serial.print("calValue = "); Serial.println(calValue);    // calValue = 72 - ошибка
 

Сотнег

★★★★★★★
15 Янв 2020
4,659
1,574
C-like:
calValue = tmpVal;
Serial.print("tmpVal = "); Serial.println(tmpVal);
Serial.print("calValue = "); Serial.println(calValue);    // calValue = 72 - ошибка
А так?
 

mir0tv0rec

✩✩✩✩✩✩✩
14 Янв 2019
24
0
Тоже самое.
Вот полный тестовый код:

C++:
#define MAX_RSH 10000 // максимальное сопротивление шунта ХXX.XX(мОм)
#define MAX_RWR 40    // максимальное сопротивление проводов от INA226 до выходной клеммы (для расчета падения напряжения)
#define MAX_CUR 500   // максимальное значение измеряемого тока Х.ХХ(А)

uint16_t rShunt = 1723;     // сопротивление шунта ХХ.ХХ(мОм)
uint16_t maxCur = MAX_CUR;  // максимальный ток на основе сопротивления шунта и калибровочного значения А (X.XX)
uint16_t minCLSB = 0;       // минимальное (максимально допустимое) разрешение для тока uA/bit
uint16_t curLSB = 0;        // разрешение для тока uA/bit
uint32_t powLSB = 0;        // калибровочное значение для мощности
uint16_t calValue = 0;      // калибровочное значение для установки мкА/бит

uint16_t wattage = 0;   // мощность


uint8_t rWire = 4;   // сопротивление проводов до выходных клемм мОм от колодки на плате БП до выходных клемм

void setCalibration(uint16_t lsb, uint16_t rSh)
{
  if (rSh < 1) rSh = 1;                                 // чтобы не было деления на ноль
  if (lsb < minCLSB) lsb =  minCLSB;                    // проверяем разрешение измерения тока
  curLSB = lsb;
  uint32_t tmpVal = (uint32_t) rSh * curLSB;            // разрешение тока мкА/бит
  Serial.print("tmpVal = "); Serial.println(tmpVal);
  tmpVal = 512000000 / tmpVal;                         // расчёт калибровочного значения
  Serial.print("tmpVal1 = "); Serial.println(tmpVal);
  calValue = tmpVal;
  powLSB = curLSB * 25;                                 // расчёт разрешения регистра мощности мВт / бит
}//end setCalibration(uint16_t lsb, uint8_t rSh)


uint16_t getPower(uint16_t val)
{
  //setCalibration(curLSB, rShunt);
  uint32_t value = val;
  value = value * powLSB;
  if (value % 100000 < 44445) value = value / 100000;
  else value = value / 100000 + 1;
  return value;  // LSB в 25 раз больше LSB для тока, умножаем возвращаем
}//end uint16_t getPower(void)

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

}

void loop() {
  minCLSB = (maxCur * 10000UL / 32768) + 1; // максимальное разрешение измерения тока мкА/бит
  Serial.print("minCLSB = "); Serial.println(minCLSB);
  Serial.print("curLSB = "); Serial.println(curLSB);
  Serial.print("rShunt = "); Serial.println(rShunt);
  Serial.print("powLSB = "); Serial.println(powLSB);
  Serial.print("Watt_Reg = "); Serial.println(wattage);
  Serial.print("Power = "); Serial.println(getPower(wattage));
  setCalibration(curLSB, rShunt);
  Serial.print("calValue = "); Serial.println(getPower(calValue));
  Serial.println("----------------------------------------------");
  delay(400);
  maxCur++;
  curLSB++;
  rShunt++;
  wattage++;

}
Вот вывод:

minCLSB = 175

curLSB = 225

rShunt = 1795

powLSB = 5600

Watt_Reg = 72

Power = 4

tmpVal = 403875

tmpVal1 = 1267

calValue = 71

----------------------------------------------
 

mir0tv0rec

✩✩✩✩✩✩✩
14 Янв 2019
24
0
Да, затупил, скопировал вывод, и забыл убрать функцию. Вс работает, теперь нужно в железе проверить...
На самом не работает здесь:

C++:
void setCalibration(uint16_t lsb, uint16_t rSh)
{
  if (rSh < 1) rSh = 1;                                 // чтобы не было деления на ноль
  if (lsb < minCLSB) lsb =  minCLSB;                    // проверяем разрешение измерения тока
  curLSB = lsb;                                         // разрешение тока мкА/бит
  calValue = 512000000 / (rSh * curLSB);                 // расчёт калибровочного значения
  writeRegister(INA226_CAL_REG_ADDR, calValue);         // Пишем значение в регистр калибровки
  powLSB = curLSB * 25;                                 // расчёт разрешения регистра мощности мВт / бит
}//end setCalibration(uint16_t lsb, uint8_t rSh)
Нужно было добавить промежуточную переменную типа uint32_t.
 

bort707

★★★★★★✩
21 Сен 2020
3,464
999
Нужно было добавить промежуточную переменную типа uint32_t.
не нужно
Достаточно привести любое из множителей к uint32
C++:
calValue = 512000000 / ((uint32_t)rSh * curLSB);
Вам бы перечитать правила приведения переменных в С/С++, а то такие вопросы задаете, что стыдно :)
Уже когда у вас элементарное присвоение calValue = tmpVal; не сработало, надо было у себя опечатку искать, а не по форумам шарится :)
 
  • Лойс +1
Реакции: mir0tv0rec

mir0tv0rec

✩✩✩✩✩✩✩
14 Янв 2019
24
0
Ну слона то я и не увидел... Вчера делал в готовом устройстве (ЛБП), а там каждый раз отключать, вынимать плату, прошивать, потом в обратном порядке все. Вот решил быстро на ардуинку перекинуть - перекинул...
C++:
calValue = 512000000 / ((uint32_t)rSh * curLSB);
Это я первым делом сделал, но...
Благодарю за помощь.