Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AVR и цифровой штангенциркуль
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
//Nikson
Здравствуйте!
Есть задумка подключить цифровой китайский штангенциркуль к АВРке и сделать некое подобие системы сбора информации о перемещении образца при испытаниях. В Интернете удалось найти зарубежные образцы, описания итд. Например, здесь подробно про протокол обмена: http://www.shumatech.com/support/chinese_scales.htm и здесь http://www.yadro.de/digital-scale/protocol.html

вроде бы всё просто, но при реализации столкнулся с кучей проблем (как со стороны "железа" штангенциркуля, так и со стороны своей программы внутри АВРки).

Если кто-нибудь уже делал что-то подобное или не лень побеседовать на эту тему - напишите плиз, а то похоже что запутался я немного, помощь нужна...

самый пока что основной вопрос - постоянные ли там данные выходят из девайса.... судя по оисанию протокола - там идут два числа - абсолютное положение и относительное.. я же принимаю контроллером полнейшую мешанину из 1 и 0, которые к тому же всё время меняются sad.gif
//Nikson
вот пока не спится (2:31) решил добавить немного инфы:

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

001111101111110001111001111100001111011111100001
001111011111100001111001111101001111101111110101
101111000000011001111100000000001111000000011101
001111000000010001111000000011001111100000000101
001111100000000101111000000011101111100000000001
001111100000001001111100000000001111000000011001
001111011111100001111001111100101111001111101101
101111000000010101111000000010101111000000011001
001111100000000101111000000010001111000000010101

... в которой распознать двоичный дополнительный код ну никак не удаётся... то ли лыжи не едут.. то ли руки...

а вот и код:

Код
#include "ioavr.h"
#include "intrinsics.h"

#define SCALE_IDLE            1
#define SCALE_SEARCHPAUSE     2
#define SCALE_WAITPAUSE       3
#define SCALE_READDATA        4
#define SCALE_READY           5

unsigned char scale_status = SCALE_IDLE;
bool scale_timer_tick = false;
unsigned int troubles = 0;
unsigned char data[50] = {0x00};
unsigned int i = 0;

volatile unsigned char input1 = 0, input2 = 0, input3 = 0;
volatile unsigned char tcnt1 = 0;

#pragma vector = INT4_vect
__interrupt void INT4_ISR(void)
{
      switch (scale_status)
      {
            case SCALE_SEARCHPAUSE: //on falling edge
            {
                  //configuire pin 6 to be sensitive to rising edge of signal
                  EIMSK &= ~(1<<INT4);
                  EICRB |=  (1<<ISC41) | (1<<ISC40);
                  EIFR  |=  (1<<INTF4);
                  EIMSK |=  (1<<INT4);

                  TCNT1 = 0;                //reset timer counter
                  scale_timer_tick = false; //clear timer flag
                  TCCR1B |= (1<<CS12) | (1<<CS10);      //start timer

                  scale_status = SCALE_WAITPAUSE;

                  break;
            }

            case SCALE_WAITPAUSE: //on rising edge
            {
                  if (scale_timer_tick)
                  {
                        //pause found, prepare to read 48 bits data
                        i = 0;
                        scale_status = SCALE_READDATA;
                  }
                  else
                  {
                        //no pause found
                        ++troubles;             //test
                        scale_status = SCALE_SEARCHPAUSE; //go back to "SEARCH PAUSE" status
                  }

                  scale_timer_tick = false; //clear flag

                  //configuire pin 6 to be sensitive to falling edge of signal
                  EIMSK &= ~(1<<INT4);
                  EICRB |=  (1<<ISC41) | (0<<ISC40);
                  EIFR  |=  (1<<INTF4);
                  EIMSK |=  (1<<INT4);

                  break;
            }

            case SCALE_READDATA: //on falling edge
            {

                  //read data three times to avoid glitches
                  input1 = PINE;
                  __delay_cycles(10);
                  input2 = PINE;
                  __delay_cycles(10);
                  input3 = PINE;

                  if ((input1 & (1<<PINE5)) && (input2 & (1<<PINE5)) && (input3 & (1<<PINE5)))
                        data[i] = 1;
                  else
                        data[i] = 0;

                  ++i;

                  if (i >= 48)
                  {
                        troubles = 0;
                        i = 0;
                        scale_status = SCALE_IDLE; < breakpoint here
                  }


                  break;
            }
      }
}

#pragma vector = TIMER1_COMPA_vect
__interrupt void TIMER1_COMPA_ISR(void)
{
      PORTC = 0xFF;
      tcnt1 = TCNT1;
      scale_timer_tick = true; //set flag
      TCCR1B &= ~((1<<CS12) | (1<<CS10));   //stop timer
      PORTC = 0x00;
}

void init_pins(void)
{
      //pin6 - PORTE4 - clock, pin7 - PORTE5 - data
      DDRE  &= ~((1<<DDE4) | (1<<DDE5));      //pins 6, 7 are set as inputs
      PORTE |=  ((1<<PORTE4) | (1<<PORTE5));  //enable pull-up resistors at pins 6, 7

      //configuire pin 6 to be sensitive to falling edge of signal
      EIMSK &= ~(1<<INT4);
      EICRB |=  (1<<ISC41) | (0<<ISC40);
      EIFR  |=  (1<<INTF4);
      EIMSK |=  (0<<INT4);

      DDRC = 0xFF;
      PORTC = 0x00;
}

void init_scale_timer()
{
      //set timer 1 to 100ms interval
      TCCR1A = 0x00;
      TCCR1B = (1<<WGM12) | (0<<CS12) | (0<<CS10); //CTC Timer1 mode, (OCR1A)
      TCCR1C = 0x00;
      OCR1A = 1210; //310 ms <============================ depend on system clock!
      TIMSK |= (1<<OCIE1A); //enable interrupt from system timer
      TIFR  |= (1<<OCF1A);  //clear flag
}

int main (void)
{

      init_pins();
      init_scale_timer();

      __enable_interrupt();

      for (;;)
      {
            if (scale_status == SCALE_IDLE)
            {
                  scale_status = SCALE_SEARCHPAUSE;
                  EIMSK |=  (1<<INT4);
            }

            __delay_cycles(10000);
      }

      return 0;
}


может свежим взглядом какой косяк заметен?
bgc
программа большая, сразу косяков не видать, может лень вчитываться и на калькуляторе времена считать...
могу предложит несколько советов:
1- раз данные меняются, значит лажа в читалке - однозначно - сначала надо добиться постоянства данных
2- начните с ловли начала посылки: через отдельный свободный пин выводите на осциллограф признак начала посылки - отладить алгоритм ловли начала (впрочем по цифрам на эту проблему не похоже)
3- по цифрам (несколько столбцов стабильных единиц) похоже что плавает времянка. Это может быть из за задержек (для считывания трех значений в обработчике прерывания). Это не клавиатура и не механический контакт. Дребезга нет, поэтому этот блок убрать совсем.
4- вывести через тестовый пин индикацию момента считывания значения бита данных - проверить по осциллографу когда это происходит.

- не очевиден алгоритм вылавливания паузы - поскольку состояния переключаются только в моменты изменения Clk, а фиксация паузы происходит не по прерываниям от Clk - алгоритм кажется кривым. Впрочем можно сделать и так (сложнее логика работы)

я бы сделал по другому: в обработчике прерывания от таймера уменьшаем счетчик
if (Cnt) Cnt--;
if (Cnt == 0) scale_status = SCALE_In_PAUSE (Находимся в паузе, ждем начала данных. Переход в прием данных по падению Clk в состоянии SCALE_In_PAUSE

в прерывании от clk (INT4) сбрасываем его в Cnt = CntMax.
aesok
С атрибутом "volatile" должны объявляться не те переменые которые используються только в прерываниях (input1, input2, input3), а те которые используються и в прерываниях и в основной программе (scale_status)!!!

Анатолий.
_Sam_
м.б. засада в устранении glitch?
Код
if ((input1 & (1<<PINE5)) && (input2 & (1<<PINE5)) && (input3 & (1<<PINE5)))
                        data[i] = 1;
                  else
                        data[i] = 0;

Если после чтения трёх значений вы при расчёте выражения в if поймаите хоть один ноль, то будете считать, что приняли ноль.
Может попробовать хотя бы так
Код
    input1 = (1 << PINE5) & PINE ? 1 : 0;
    __delay_cycles(10);
    input2 = (1 << PINE5) & PINE ? 1 : 0;
    __delay_cycles(10);
    input3 = (1 << PINE5) & PINE ? 1 : 0;

    data[i] = (input1 + input2 + input3 > 1) ? 1 : 0;

Код конечно не оптимальный, но идея думаю ясна. Если приняли два и более раза одно состояние, то считаем его устойчивым.
//Nikson
спасиб за советы, но пока что всё равно не работает (хех, никогда и ничто с первого раза нормально не работает sad.gif)

меня ещё вот что настораживает...
по сути дела программа вклинивается в протокол обмена в случайном месте, а для того чтобы начать приём точно двух предаваемых слов и проводится процедура "синхронизации" - поиска большой паузы между сообщениями. так вот, в случае "неудачного" запроса (когда обратились в момент передачи а не в паузу), снова настраиваемся ловить паузу, и для проверки ввёл переменную troubles - она в итоге показывает, сколько было неверных попыток засинхронизироваться на одну удачную попытку чтения.. так вот, это число почему-то всё время равно 14. счётчик-то обнуляется после удачного чтения, но в следующий раз снова - 14 неудачных попыток, потом проходит чтение.. ИМХО явно что-то не так sad.gif

и ещё... на осциллографе данные всё-таки тоже "бегают". ещё есть слабая надежда что это просто последние разряды дёргаются (что вполне терпимо)... а принимаю просто неправильно и поэтому сбоит и в начале и в середине (что совсем неприемлимо)...

неужели китайцы всё-таки поменяли протокол...

да, и ещё - в ИАРе можно как-нибудь значение переменной сохранить в файл, в буфер обмена?

решил пока что без "синхронизации" - просто получить например 1000 значений и вручную посмотреть, поанализировать... ну, получил огромный массив, вроде есть повторяющиеся участки.. распечатать бы, да вот из окошка watch не копируется никуда sad.gif

я тут через "Быстрый ответ" дописываю сообщения, а они всё в последнее добавляются. на самом деле это много сообщений smile.gif

мысли вслух насчёт алгоритма... подумалось так сделать: берём массив на сотню значений и просто их всех ловим, как перестали идти цифры - пачка кончилась, отсчитываем назад 23 значения и считаем... сейчас буду пробовать.

и ещё - удивило, что почти ничего не удалось найти по теме. только вот те 2 ссылки что привёл в первом сообщении... неужели народ не пользуется? может есть какие-нибудь ещё недорогие датчики линейного пермещения, а я просто не знаю и впустую вожусь с этим штангенциркулем?
_Sam_
Цитата
процедура "синхронизации"

Может синхронизацию по другому сделать.
Частота колка ведь вам известна. Также известно, что когда заканчивается посылка, заканчиваются клоки. Тогда, чтобы поймать конец посылки, надо замерять время м/у клоками, как только оно превысит раза в два заданное время, считать, что посылка кончилась. Если до конца посылки клоков было сосчитано меньше, чем задано по протоколу, считать посылку принятой не полностью.

Цитата
может есть какие-нибудь ещё недорогие датчики линейного пермещения, а я просто не знаю и впустую вожусь с этим штангенциркулем?

дороговизна датчика зависит от класса его точности и допускаемых условий эксплуатации. У штангенциркуля ход небольшой, да и класс точности какой у него? Могут возникнуть проблемы при установке штангенциркуля на ваше устройство. Перекосы всякие и т.д. Наверное более дешёвый вариант датчика на базе оптической мыши.
//Nikson
Цитата(_Sam_ @ May 6 2007, 14:40) *
Может синхронизацию по другому сделать.


кстати, ещё идея пришла... я всю эту ерунду с синхронизацией затеял чтобы ненароком не попасть началом считывания уже в процесс передачи. но время посылки примерно 800 мкс, а пауза - 300 мс. разница более чем в 500 раз. соответственно и шансы попасть "не туда" 1:500. так может ну к чёрту всё это - просто взять да и тупо без всяких синхронизаций раз 100 прочитать данные по 48 бит, выкинуть лишнее...

Цитата(_Sam_ @ May 6 2007, 14:40) *
У штангенциркуля ход небольшой, да и класс точности какой у него? Могут возникнуть проблемы при установке штангенциркуля на ваше устройство.


зато даже этот китайский штангенциркуль внесён в реестр средств измерений и имеет сертификат smile.gif
поэтому и взял его. как крепить - дело десятое (немцы на станки их крепят же.... ссылка в первом посте)...

основная проблема - всё-таки какой там протокол обмена. если китайцы заложили туда какую-нибудь секретность (чего раньше не было), то я точно ничего не вытащу из этих данных. поэтому и нужен человек, который сам сталкивался....
Dog Pawlowa
Цитата(//Nikson @ May 6 2007, 16:03) *
кстати, ещё идея пришла... я всю эту ерунду с синхронизацией затеял чтобы ненароком не попасть началом считывания уже в процесс передачи. но время посылки примерно 800 мкс, а пауза - 300 мс. разница более чем в 500 раз. соответственно и шансы попасть "не туда" 1:500. так может ну к чёрту всё это - просто взять да и тупо без всяких синхронизаций раз 100 прочитать данные по 48 бит, выкинуть лишнее...
зато даже этот китайский штангенциркуль внесён в реестр средств измерений и имеет сертификат smile.gif
поэтому и взял его. как крепить - дело десятое (немцы на станки их крепят же.... ссылка в первом посте)...

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

Да, применение штангенциркуля - тема интересная. Нужно будет попробовать.
Разбираться в тексте программы не буду, я бы отладку делал так -
1) взял бы на полке цифровой осциллограф
2) убедился бы, что коды совпадают визуально
3) доработал бы программу, чтобы в моменты синхронизации контроллер выдавал импульс, который можно было бы наблюдать вторым каналом осциллографа.
Дальнейшие действия - в зависимости от результатов.
Kovrov
Цитата(//Nikson @ May 6 2007, 01:38) *
Здравствуйте!
Есть задумка подключить цифровой китайский штангенциркуль к АВРке и сделать некое подобие системы сбора информации о перемещении образца при испытаниях.

А где это такая штука продается?
у меня слесаря на работе все пристают ко мне чтоб я сделал измеритель перемещения для фрезерного станка....
Dog Pawlowa
Цитата(Kovrov @ May 6 2007, 18:38) *
А где это такая штука продается?
у меня слесаря на работе все пристают ко мне чтоб я сделал измеритель перемещения для фрезерного станка....

Я покупал в стране по той ссылке за 10 Евро. Причем в каком-то киоске левом.
Может, в продвинутых строительных магазинах есть, типа OBI.

Гугл рулит, но цена в России, конечно... 1500 руб в пять раз дороже? ohmy.gif
//Nikson
Цитата(Kovrov @ May 6 2007, 17:38) *
А где это такая штука продается?
у меня слесаря на работе все пристают ко мне чтоб я сделал измеритель перемещения для фрезерного станка....

я из Минска. не думаю, что Вам интересно где у нас их продают smile.gif
может в каких-нибудь магазинах.. не знаю. сюда контора прямо из Китая возит. (у нас же блин Китай - стратегический партнёр biggrin.gif )

такс... по теме.... могу сказать теперь уже на 90% - это всё-таки бегают данные на выходе штангенциркуля, т.е. там не просто два числа по клоку идут, как было описано у капиталистов на сайте (в приницпе, 150 баксов они не просто так хотят за софт для связи).... а счастье было так близко
biggrin.gif обманули, похоже...

вот считал подряд 1000 бит данных, просто, без синхронизации, проанализировал - да, вроде есть повторяющиеся участки (если кому интересно - см. присоединённый файл)...

кстати, у меня ж ещё есть в единственном экземпляре шнурок для подключения этой радости к RS232 - там стоит микросхема со спиленной маркировкой, на ПИК смахивает... на её входе - данные "бегают", на выходе - стабильно. то есть там скорее всего какой-то алгоритм обработки присутствует... вроде есть упоминания некоего протокола Sylvac, но пока конкретно найти не удалось... если кто что знает - подскажите.
sensor_ua
Я бы всё-таки записал и посмотрел внимательно. А приём, похоже удобнее таки на синхронном UART или SPI сварганить с внешеним решением синхро для посылки - хотя бы те же данные запихать на прерывание проца и включать/выключать
Nanobyte
А может сначала попробовать собрать интерфейс по первой ссылке (YADRO), да расковырять HEX для Tiny2313? Они ведь этот код как-то принимают.
Pyku_He_oTTyda
Завтра спрошу на работе, где такие штангели покупали
satellite-plus
Цитата(//Nikson @ May 6 2007, 00:38) *
Здравствуйте!
Есть задумка подключить цифровой китайский штангенциркуль к АВРке и сделать некое подобие системы сбора информации о перемещении образца при испытаниях. В Интернете удалось найти зарубежные образцы, описания итд. Например, здесь подробно про протокол обмена: http://www.shumatech.com/support/chinese_scales.htm и здесь http://www.yadro.de/digital-scale/protocol.html

вроде бы всё просто, но при реализации столкнулся с кучей проблем (как со стороны "железа" штангенциркуля, так и со стороны своей программы внутри АВРки).

Если кто-нибудь уже делал что-то подобное или не лень побеседовать на эту тему - напишите плиз, а то похоже что запутался я немного, помощь нужна...

самый пока что основной вопрос - постоянные ли там данные выходят из девайса.... судя по оисанию протокола - там идут два числа - абсолютное положение и относительное.. я же принимаю контроллером полнейшую мешанину из 1 и 0, которые к тому же всё время меняются sad.gif

Вроде на выход идут синхро и данные. Необходимо совместить уровни. Штангель иногда меняет скорость передачи. Программу прилагаю. Писал давно многое подзабыл. Но работало.
//Nikson
спасибо всем, принявшим участие в обсуждении!
немного поменял алгоритм (максимально укоротил процедуру обработки прерывания по заднему фронту клока) и главное - поставил кварц побыстрее - и вот под утро всё заработало!!!

всё оказалось так просто, что даже обидно - 2 ночи безвылазно просидел - по неопытности наверное sad.gif

ЗЫ. я щаслив :D

PPS. всё работает точно как было и описано в первых двух ссылках - ничего товарисчи китайцы не меняли в протоколе, как говорится, "внимательно читай мануал"
aleksey_g
Цитата(//Nikson @ May 7 2007, 09:37) *
спасибо всем, принявшим участие в обсуждении!
немного поменял алгоритм (максимально укоротил процедуру обработки прерывания по заднему фронту клока) и главное - поставил кварц побыстрее - и вот под утро всё заработало!!!


Хочется Вас поздравить!
Все, как по нотам. Если собрал устройство... программу... и все сразу заработало, ищите ошибку!
Многие проходят этот путь, если не все.
dem-vr
5 лет назад я подключал эту диковинку к AT90S8515 и кидал информацию в персоналку.
Это маленькаяч инструкция, которая Вам поможет в этом деле!
Stas62
Цитата(//Nikson @ May 7 2007, 10:37) *
спасибо всем, принявшим участие в обсуждении!

PPS. всё работает точно как было и описано в первых двух ссылках - ничего товарисчи китайцы не меняли в протоколе, как говорится, "внимательно читай мануал"


У меня похожая задача. хочу мерять вес через линейное перемещение подпружиненной системы
//Nikson
Цитата
У меня похожая задача. хочу мерять вес через линейное перемещение подпружиненной системы


а быть может вес лучше мерять через усилие на упругой мембране? тогда можно посмотреть в сторону датчика fss1500 и аналогичных...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.