Хронограф : измеритель скорости пули. От простого к сложному

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

заодно подсветку в дисплее пожалуй переделаю на оранжевую, ну так хотелка, нравится оранжевая подсветка, контрастно и глаза не раздражает

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

jeka_tm, вот написал пример  измерителя под твою задачу. Характеристики следующие - измеряет таймером1 длительность между двумя импульсами на их первом спадающем фронте (falling) , максимальное измеряемое время - 4095 µS, минимальное не тестировал. Относительная точность измерения: +/- 0,2µS.   Т.к. я потихоньку изучаю асм, то немог упустить случая поупражняться, и вставил немножко кода на асме ))  Особенности: в ассемблерном фрагменте в качестве флагов используются два свободных регистра от портов PB6, PB7 (ноги отключены от портов, т.к. на этих пинах висит кварц, а регистры можно задействовать для своих нужд). В строке 4 выключен таймер0, его можно включить, но тогда в случае одновременного прихода прерываний от таймера0 и таймера1  измерение произойдёт с ошибкой в несколько микросекунд.

void setup(){
Serial.begin(9600);
pinMode (8,INPUT); // вход сигнала 
TCCR0B=0; TIMSK0=0;
TCCR1A = 0; TCNT1 = 0; 
TIMSK1 = (1<<ICIE1)|(1<<TOIE1);
TCCR1B = (1<<ICNC1)|(1<<CS10);
}

ISR (TIMER1_CAPT_vect){ asm ( 
"sts 0x85, __zero_reg__" "\n\t"
"sts 0x84, __zero_reg__" "\n\t"
"sbic 0x05,6"            "\n\t" 
"sbi 0x05,7"             "\n\t" 
"sbi 0x03,6"             "\n\t"
: : : );
}//end isr

ISR (TIMER1_OVF_vect) {PORTB&=~(1<<6);} 

void loop(){
if (PORTB&1<<7) { Serial.print( (float) ICR1 * 0.0625f); 
                  PORTB&=~(1<<7); //снять флажок готовности данных
                  Serial.println(" microseconds"); }
}//end loop

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

спасибо. буду пробовать. если правильно понял этот коэффициент для 16мгц, для другой частоты другой. так?

0.0625f

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

jeka_tm, ну да. Константа в микросекундах = 1 / частота в мегагерцах.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

хорошо. а то в моем 24мгц, а люди на 16мгц собирают

micros или millis получается использовать нельзя если разрешить измерение

PORTB&=~(1<<7);// разрешаем новое измерение

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

jeka_tm, таймер0 нежелательно использовать, будут ошибки, хоть и незначительные.  Кстати это флажок не разрешения измерения, а он констатирует факт , что сработал второй импульс и можно считать новое значение. Так-же он помогает не выводить в цикле одно и тоже. Значение ICR1 обновляется фактически только после нового измерения, так что будет хранить старое до упора если новое не поступает. Механизма запрещения измерения тут нет.

 

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

вроде понял

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

dimax изза этой строки дисплей перестал работать //TCCR0B=0; 

не блокируется каким то образом пины? у меня используются 5 6 7

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

jeka_tm, у тебя библа дисплея использует таймер0 (через delayMicroseconds)  Нужно либо другую библу, которая не использует задержки в работе, либо смириться с возможными ошибками в измерении времени. Третьего не дано :)
 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

для начала решил пины поменять. задержки при инициализации дисплея нужны, потом не нужны. еще delay используется для кнопок

maxelectro93
Offline
Зарегистрирован: 03.04.2016

Куплю готовый хронограф,можно без корпуса(только спаеную внутрянку),только трубка с датчиками должна быть 10 см,и диаметром 20 мм. Связь личным сообщением вконтакте https://vk.com/maxiplus

han2001
Offline
Зарегистрирован: 09.01.2015

Здравствуйте!

jeka_tm и dimax есть ли какие продвижения по модернизированному хронографу?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

han2001
Offline
Зарегистрирован: 09.01.2015

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да попробуй. только пины дисплея проверь. может у тебя по другому сделано

https://yadi.sk/d/5uGYVlRitYVcN

han2001
Offline
Зарегистрирован: 09.01.2015

Вообщем опробовал новый код, ниже моирезультаты, но предварительно уточню по используемой ардуинке. Я использую такую ардуинку.

Что заметил. 

1.Первоначальный экран рисуется.

2. Нет обработки кнопок меню, вообще ноль реакции на нажатие.

3. харкнул бумажкой через трубку с датчиками. Скорость бешенная от 300м/с до 600м/с и рисует одно деление в левом верхнем углу. Но "измеряет" только один раз, дольше вообще ноль реакции, приходится передергивать питание. Уточнение: датчики подключены по старому к 2 и 3 выводу ардуинки, т.к. у меня уже собранный хронограф.

Что касается стабильности измерений в рабочей прошивке, то ниже на картинке мои измерение. Для этого я собрал на ПЛИС так называемый генератор выстрелов,  импульсы с которого подавал именно на светодиоды хронографа, отвязав их от питания.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

спасибо. буду разбираться

han2001
Offline
Зарегистрирован: 09.01.2015

Здравствуйте jeka_tm!

Есть ли какие подвижке в оновленном хронографе?

С удовольствием оттестировал бы новую версию, я сново собрал генератор выстрелов на ПЛИС.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

пример мне нужен потому что я сам в этих найстройках таймеров не разбираюсь

+ нашел пример. постараюсь в ближайшие дни допилить

han2001
Offline
Зарегистрирован: 09.01.2015

Здравствуйте jeka_tm!

Есть ли какае результаты, получилось ли чего?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

привет. извини. замотался. вылетело из головы

han2001
Offline
Зарегистрирован: 09.01.2015

Да извеняться особо не за что, понятно дело, что это только хобби. Я сам только в отпуск ушел, появилось время вот и решил спросить, так как темя для меня интересна,  а на таком уровне программирования мозгов не хватает.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да какой там уровень. знал бы ты мой))

han2001
Offline
Зарегистрирован: 09.01.2015

По работе мастера видно)))

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

#include "util/delay.h"
#include "lcd1202.h"

LCD1202 lcd(8, 7, 6, 5);  // RST, CS, MOSI, SCK

#define pin_1       A2
#define pin_2       A4

boolean color=1;

double data=0;

volatile unsigned char s1 = 0;
volatile unsigned char s2 = 0;

// Timer/Counter 0 initialization
void Timer0_Init(void){
  TCNT0 = 0;
  TCCR0A = 0;
  TCCR0B = 0;
  TIMSK0 = 0;
  TIFR0 = 0;
}

// Timer/Counter 1 initialization
void Timer1_Init(void){
  TCNT1 = 0;
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1C = 0;
  TIMSK1 = 0;
  TIFR1 = 0;
}

void setup(){
  lcd.Inicialize();
  vyvod(data);
  cli();         // Global disable interrupts
  Timer0_Init(); // Timer/Counter 0 initialization
  Timer1_Init(); // Timer/Counter 1 initialization
  sei();         // Global enable interrupts

  attachInterrupt(0, sensor_1, FALLING);
  attachInterrupt(1, sensor_2, FALLING);
}

void loop(){
  while ( s1 == 0 && s2 == 0 ) ;
  _delay_ms(800); // wait 800 ms

  if ( s1 != 0 && s2 != 0 ){
    data = 0.07 / (TCNT1 * (1.0 / 24000000.0)); // v = s / t
  }
  else{
    data = 0;
  }

  //Serial.println(data);
  vyvod(data);

  TCCR1B = 0;
  TCNT1 = 0;

  s1 = 0;
  s2 = 0;
}

void sensor_1(){
  if ( s1 == 0 ){
    TCCR1B = (1<<CS10); // Timer/Counter 1 running (no prescaling)
    s1 = 1;
  }
}

void sensor_2(){
  if ( s2 == 0 ){
    TCCR1B = 0; // Timer/Counter 1 stopped (no clock source)
    s2 = 1;
  }
}

//========================================================================
//                         Вывод текущей скорости
//========================================================================
void vyvod(int skor){
  unsigned int temp=skor;                         // переменная для хранения
  unsigned int c4=temp%10;                        // четвертая цифра скорости 
  temp/=10;
  unsigned int c3=temp%10;                        // третья цифра скорости 
  temp/=10;
  unsigned int c2=temp%10;                        // вторая цифра скорости 
  temp/=10;
  unsigned int c1=temp%10;                        // первая цифра скорости

  lcd.simb16x32(9,  17, color, c1);
  lcd.simb16x32(29, 17, color, c2);
  lcd.simb16x32(49, 17, color, c3);
  lcd.simb10x16(75, 17, color, c4);
  lcd.Update();
}

либа находится тут в папке дисплеи

кстати меньше 15м/с для расстояния между датчиками 60мм выдавать будет чушь, минимум скорости считается:

0.06 / 0.004096 = 14.6484 м/с

 

han2001
Offline
Зарегистрирован: 09.01.2015

Чего то вообще ни чего не кажет дисплей. Посмотрел осцилографом, сигналов нет на 5,6,7, а 8 у меня с самаго начала к питанию подвязан.

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

у меня показывал и измерял. я кидал болтик. но скорость маленькая, счетчик переполняется и начинаем по новой поэтому чушь показывает. 8 надо оставить свободным. он для ресета дисплея предназначен, а у меня он изначально на 3.3В посажен. мне просто не хочется гаусс доставать,  у кого пневматика есть быстрее проверить

han2001
Offline
Зарегистрирован: 09.01.2015

Предыдущие версии у меня работают, а эта не хочет. Может из-за того что у меня леонардо, а тут еще и работа с регистрами, вообщем в никакую, сигналов вообще нет по линиям дисплея с момента подачи питания. А вообще правильно ли я закинул. Создал папку со скетчем и туда же закинул библиотеку дисплея скаченную с вашего яндекс диска, 2 файла с расширением h и один с расширением cpp.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

неправильно. ты библиотеку ни разу не ставил? погугли

han2001
Offline
Зарегистрирован: 09.01.2015

Да не приходилось раньше ставить библиотеки. Поставил все через меню IDE как положено, сигналы разово по линиям кидаются после включения питания, но картинки все равно нет. Может быть это из-за сигнала сброса поданного не во время. Может его стоит все таки оторвать от RC цепочки  (у себя я так сброс организовал) и припоять его к 8 выводу? Если это так, то эту теорию я смогу проверить только завтра вечером, когда к паяльнику доберусь.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

я вспомнил. там в коде отображение только после выстрела. перепаивать не надо

поправил код чтобы экран не был пустым при включении, чтобы тебя не смущало

han2001
Offline
Зарегистрирован: 09.01.2015

Сам сразу не сообразил посмотреть на обновление экрана по воздействию. Да картинка есть, но показывает фигню. Сначала плювался бумажкой (старая программа показывала порядка 17м/с) значения разные 5,9,7,10. Думал может срабатывает ограничения по минимальной скорости о которых вы писали выше. Пошел стрельнуть из пневматики (скорость порядка 109-111м/с по измерениям старой программы). Сделал порядка 15 выстрелов. 2-3 выстрела не определила скорость, скорее всего несоосность хронографа. А вот остальные 12-13 выстрелов около 16.5-17.2 м/с. Но здесь я думаю имеет значение в программе расстояния между датчиками, у вас он было 0.07, я его поменял на свои 0.105. Поставил обратно ваше значение 0.07, стало порядка 11м/с, хотя реально у меня расстояние между датчиками 10см. Можно сказать работает на больших скоростях, но значения показываюся деленными на 10.

han2001
Offline
Зарегистрирован: 09.01.2015

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

Еще заметил, что у вас в формуле расчета скорости стоит 24000000 - это я так понимаю частота кварца процессора? А уменя 16М, т.е. для себя я должен ее выставить в фомуле?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а ардуина у тебя 16мгц? там в формуле фигурирует частота

han2001
Offline
Зарегистрирован: 09.01.2015

Не успел откорректировать предыдущий пост, вы уже ответили. Вечером попробую еще поэкспериментировать, но все же чего не так с значениями деленными на 10

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да все просто. все дело в выводе значений. подправляю. пока без десячиных. смотри число целиком

han2001
Offline
Зарегистрирован: 09.01.2015

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

Основное окно

#include <font.h>
#include <lcd1202.h>
#include "util/delay.h"


LCD1202 lcd(8, 7, 6, 5);  // RST, CS, MOSI, SCK

#define pin_1       A3
#define pin_2       A2
#define accum       A0
#define W   94
#define H   66
byte S = 1;
boolean color=1;
int U = 0; //для расчета батарейки
int a = 0; //для расчета батарейки
double data=0;

volatile unsigned char s1 = 0;
volatile unsigned char s2 = 0;

// Timer/Counter 0 initialization
void Timer0_Init(void){
  TCNT0 = 0;
  TCCR0A = 0;
  TCCR0B = 0;
  TIMSK0 = 0;
  TIFR0 = 0;
}

// Timer/Counter 1 initialization
void Timer1_Init(void){
  TCNT1 = 0;
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1C = 0;
  TIMSK1 = 0;
  TIFR1 = 0;
}

void setup(){
  lcd.Inicialize();
  vyvod(data);
  cli();         // Global disable interrupts
  Timer0_Init(); // Timer/Counter 0 initialization
  Timer1_Init(); // Timer/Counter 1 initialization
  sei();         // Global enable interrupts

  attachInterrupt(0, sensor_1, FALLING);
  attachInterrupt(1, sensor_2, FALLING);
}

void loop(){
  while ( s1 == 0 && s2 == 0 ) ;
  _delay_ms(500); // wait 500 ms

  if ( s1 != 0 && s2 != 0 ){
    data = 0.106 / (TCNT1 * (1.0 / 16000000.0)); // v = s / t
    data*=10;
  }
  else{
    data = 0;
  }

  //Serial.println(data);
  vyvod(data);
  battery();
  TCCR1B = 0;
  TCNT1 = 0;

  s1 = 0;
  s2 = 0;
}

void sensor_1(){
  if ( s1 == 0 ){
    TCCR1B = (1<<CS10); // Timer/Counter 1 running (no prescaling)
    s1 = 1;
  }
}

void sensor_2(){
  if ( s2 == 0 ){
    TCCR1B = 0; // Timer/Counter 1 stopped (no clock source)
    s2 = 1;
  }
}


Вкладка

void vyvod(int skor){
  unsigned int temp=skor;                         // переменная для хранения
  unsigned int c4=temp%10;                        // четвертая цифра скорости 
  temp/=10;
  unsigned int c3=temp%10;                        // третья цифра скорости 
  temp/=10;
  unsigned int c2=temp%10;                        // вторая цифра скорости 
  temp/=10;
  unsigned int c1=temp%10;                        // первая цифра скорости
  
  //отображаем скорость
  lcd.simb16x32(9,  17, color, c1);
  lcd.simb16x32(29, 17, color, c2);
  lcd.simb16x32(49, 17, color, c3);
  lcd.simb10x16(75, 17, color, c4);
  
  //рисуем основное меню
  lcd.drawRect(S,  S, W, H, color); //внешниий прямоугольник
  lcd.drawRect(S, 12, W, 44, color); // внутренний прямоугольник
  lcd.drawFastVLine(48, 2, 11, color); //верхняя вертикальная разделительная черта
  lcd.drawFastVLine(48, 56, 11, color); //нижняя вертикальная разделительная черта
  lcd.drawBitmap(68,33, image, 24, 16, color); //символ М/S с верхней чертой под дробной частью скорости
  lcd.print(13, 57, color, "Меню");
  lcd.print(55, 57, color, "Данные");
  lcd.drawRect(79, 3, 14, 8, color);  // контур батарейки
  lcd.drawFastVLine(78, 5, 4, color); //
  
  lcd.Update();
}

//считаем состояние батарейки
void battery(){
  U = analogRead(accum);
  U = constrain(U, 650, 855);
  U = map(U, 650, 855, 0, 9);
  lcd.fillRect(80, 5, 10, 4, !color); //очищаем рисунок состояния батарейки
  for( a=0;a<=U;a++) lcd.drawFastVLine(90-a, 5, 4, color); // рисуем состояние батарейки
  lcd.Update();
}

 

han2001
Offline
Зарегистрирован: 09.01.2015

Если так, то все работает

#include <font.h>
#include <lcd1202.h>
LCD1202 lcd(8, 7, 6, 5);  // RST, CS, MOSI, SCK

#define accum       A0
#define W   94
#define H   66
byte S = 1;
boolean color=1;
int U = 0; //для расчета батарейки
int a = 0; //для расчета батарейки

void setup() {
 lcd.Inicialize();

}

void loop() {
  battery();

}

void battery(){
  U = analogRead(accum);
  U = constrain(U, 650, 855);
  U = map(U, 650, 855, 0, 9);
  lcd.drawRect(79, 3, 14, 8, color);  // контур батарейки
  lcd.drawFastVLine(78, 5, 4, color); //
  lcd.fillRect(80, 5, 10, 4, !color); //очищаем рисунок состояния батарейки
  for( a=0;a<=U;a++) lcd.drawFastVLine(90-a, 5, 4, color); // рисуем состояние батарейки
  lcd.Update();
}

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

потому что 54 строка блокирует

han2001
Offline
Зарегистрирован: 09.01.2015

Спасибо, че то сам не сообразил. Двигаюсь дальше. jeka_tm вы как то писали 

кстати меньше 15м/с для расстояния между датчиками 60мм выдавать будет чушь, минимум скорости считается:

     0.06 / 0.004096 = 14.6484 м/с

0,06 это расстояние между датчиками
а что такое 0.004096?
 

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

0,06 между датчиками в метрах. второе не помню. вспомню скажу

 

han2001
Offline
Зарегистрирован: 09.01.2015

Вообщем если принять значение 0.004096 за константу, то для моего хроногрова с расстоянием между датчиками 106мм (значение откалибровано по осцилографу и генератору выстрелов) расчеты совпадают. При скорости до 25м/с хронограф показывает хрень (в зависимости от заданной скорости хронограф показывал значения 44, 88 и даже 737м/с), а вот при скорости от 26м/с показывает точное значение. С помощью генератора выстрелов заметил, что к скорости около 500м/с погрешность измерения составляет 1м/с, при скорости 350 м/с погрешность около полуметра. Вообщим отличные результаты по сравнению с прошлой версией, где при скорости 500м/с погрешность доходила до 10м/с, хотя и эти результаты быле вполне приемлемы. Но чем точнее тем лучше.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

han2001
Offline
Зарегистрирован: 09.01.2015

Так я к светодиодам подкючался, а не ко входу ардуины, т.е. хронограф проверялся с учетом оптопары. Правда тут есть момент. Когда я работаю от генератора выстрелов, то светодиоды гаснут полностью и с крутыми фронтами, т.е. идеальные условия, а когда будет пролетать пуля, то тут может возникнуть небольшая несоосность выстрела или постепенное перекрытием светодиодов по ходу пролета пули, но все это отрабатывалось на прошлой версии на скоростях около 280м/с и все работало. 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

круто. спасибо. буду знать

han2001
Offline
Зарегистрирован: 09.01.2015

Правда есть еще один момент, с фототранзисторами у меня так и не получилось получить хороших результатов и я перешел на фотодиоды.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

как подключал фотодиоды? название. схема с компаратором?

блин столько можно проектов допилить, но времени совершенно нет

han2001
Offline
Зарегистрирован: 09.01.2015

Фотодиоды использовал такие . Ни ккие компараторы не ставил, просто вместо фототранзистора воткнул фотодиоды и поменял резисторы.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

не могу найти характеристики фотодиода

han2001
Offline
Зарегистрирован: 09.01.2015

Вродо он