Обработка данных с цифрового штангенциркуля.

bifurkas
Offline
Зарегистрирован: 27.10.2013

Потребовалось данные, получаемые с цифрового штангенциркуля, отображать на семисегментном индиаторе. Сам протокол данных представляет из себя SPI, только однонаправленный - от штангенциркуля идёт два сигнала: синхронизации и непосредственно данных. Вот они на картинке:

Такие посылки данных штангенциркуль выдает 4 раза в секунду. Каждая посылка состоит из 3 байт. Сначала передается младший байт. Внутри байта порядок следования бит тоже начинается с младшего. Первым приходит младший бит а затем страшие.  Первые два байта содержат непосредственно данные об измерениях в сотых долях миллиметра. Третий байт содержит бит-признак отрицательного числа. Инвертируем все 3 байта, переворачиваем, переводим в десятичную систему, делим на 100, получаем значение в миллиметрах. На осциллограмме штангенциркуль передает число 6,75 мм.

С отображением значения на индикаторе у меня вопросов не возникает, а вот как получить десятичное значение - проблема для меня. Если кто поможет фрагментом кода или хотя-бы направлением действия - буду весьма признателен!

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

bifurkas пишет:

как получить десятичное значение - проблема для меня. 

Так Вы ж вроде уже всё сделали!

Вот смотрите, Вы пишете

bifurkas пишет:

делим на 100, получаем значение в миллиметрах. 

Ну и давайте добавим: "берём остаток от деления на 100 и получаем сотые доли миллиметра".

И Всё. Если всё остальное правильно, конечно.

 

 

bifurkas
Offline
Зарегистрирован: 27.10.2013

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

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

bifurkas пишет:

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

ничего не понимаю, ну деление на 100 Вы же написали? Так напишите взятие остатка (то же самое, только вместо / используйте %)

Araris
Offline
Зарегистрирован: 09.11.2012
bifurkas
Offline
Зарегистрирован: 27.10.2013
sandr4
sandr4 аватар
Offline
Зарегистрирован: 11.02.2015

  Araris, + 100 в карму))).

Araris
Offline
Зарегистрирован: 09.11.2012

Спасибо за спасибо, да, есть один тайный способ, делюсь : https://www.google.com.ua/?gws_rd=ssl#q=arduino+caliper

bifurkas
Offline
Зарегистрирован: 27.10.2013

Вот окончательный код, может пригодиться кому:

#include "LedControl.h" // библиотека для работы с МАХ7219
LedControl lc=LedControl(12,11,10,1); 
/*
 pin 12 DataIn 
 pin 11 CLK 
 pin 10 LOAD 
 1 - используем одно устройство
 */
int i;
int ones1;  //установка единиц
int tens1;  //установка десятки
int hundreds1;  //установка сотни
int thousands1; //установка тысячи
int T;     // значение сигнала Stop
int ones;  //единицы
int tens;  //десятки
int hundreds;  //сотни
int thousands; //тысячи
int sign;
long value;
float result; //текущее значение
int clockpin = 4;  //вывод CLOCK штангенциркуля
int datapin = 5;   //вывод DATA штангенциркуля
unsigned long tempmicros;

 void setup() {
  lc.shutdown(0,false); 
  lc.setIntensity(0,6); //яркость от 1 до 15
  lc.clearDisplay(0); //очистка дисплея
  T=3456; //первоначальное значение сигнала Stop
  digitalWrite(2,HIGH); // подтягивающие резисторы на кнопки
  digitalWrite(3,HIGH);
  digitalWrite(6,HIGH);
  digitalWrite(7,HIGH);
  pinMode(clockpin, INPUT);
  pinMode(datapin, INPUT);
  pinMode(13, OUTPUT); //индикация достижения значения STOP
}
 void loop () {

  if(digitalRead(7)==LOW)
  {T++; //увеличиваем сотые
  delay(100);}
  if(digitalRead(6)==LOW)
  {T--; //уменьшаем сотые
  delay(100);
  }
    if(digitalRead(2)==LOW)
  {T=T+100; //увеличиваем мм
  delay(200);
  }
    if(digitalRead(3)==LOW)
  {T=T-100; //уменьшаем мм
  delay(200);
  }
  if(T>9999)
  {T=9999;} // ограничение показаний до 99.99мм
   if(T<0)
  {T=0;} // ограничение показаний от 0мм 
  thousands1 = T/1000;
  hundreds1 = (T-thousands1*1000)/100;
  tens1=(T-(thousands1*1000+hundreds1*100))/10;
  ones1=T-(thousands1*1000+hundreds1*100+tens1*10);
  lc.setDigit(0,3,thousands1,false);
  lc.setDigit(0,2,hundreds1,true);
  lc.setDigit(0,1,tens1,false);  
  lc.setDigit(0,0,ones1,false);
  
  while (digitalRead(clockpin)==HIGH) {} //if clock is LOW wait until it turns to HIGH

  tempmicros=micros();

  while (digitalRead(clockpin)==LOW) {} //wait for the end of the HIGH pulse

  if ((micros()-tempmicros)>500) { //if the HIGH pulse was longer than 500 micros we are at the start of a new bit sequence

    decode(); //цикл декодирования данных

  }
}

void decode() {

  sign=1;

  value=0;

  for (i=0;i<23;i++) {

    while (digitalRead(clockpin)==HIGH) { } //wait until clock returns to HIGH- the first bit is not needed

    while (digitalRead(clockpin)==LOW) {} //wait until clock returns to LOW

    if (digitalRead(datapin)==LOW) {

      if (i<20) {

        value|= 1<<i;
      }
      if (i==20) {
        sign=-1;
      }
    }
  }
  result=(value*sign);    
  thousands = result/1000;
  hundreds = (result-thousands*1000)/100;
  tens=(result-(thousands*1000+hundreds*100))/10;
  ones=result-(thousands*1000+hundreds*100+tens*10);
  lc.setDigit(0,7,thousands,false);
  lc.setDigit(0,6,hundreds,true);
  lc.setDigit(0,5,tens,false);  
  lc.setDigit(0,4,ones,false);
  if (result>T) {
  digitalWrite(13, HIGH); }
  else {digitalWrite(13, LOW); }
}

Не претендую на гладкость и лаконичность написания, т.к. программирую раз в год, но работает. Программа непрерывно выводит данные с цифрового штангенциркуля на 4 семисегментных индикатора, на втором таком индикаторе кнопками устанавливается значение, при достижении которого загорается светодиод. Мне это понадобилось для самодельного ЧПУ самодельного листогиба.

Да, забыл написать - сигналы с штангенциркуля инвертированы аппаратно (согласование уровней).