Детектор металла DC42 улучшение

Тед
Пн 25 декабря 2017 г., 20:17
Я только что наткнулся на интересный проект детектора металлов CD42, ссылка ниже
Это может быть значительно улучшено, используя аудио -усилитель для энергии TX -катушки, TDA2030 увеличивается в 20 раз превышает интенсивность электромагнитного поля, используя последовательный резонанс CT и TX Coil.
Больше улучшений может быть сделано с помощью модификаций программы, я знаю, что электроника не программирование.
Есть ли кто -то, кто заинтересован, присоединился ко мне в этом улучшении ?

https: // github.com/dc42/arduino/blob/ma ... эматический.JPG
TDA2030; https: // m.aliexpress.com/item/32814901629.HTML

Ахулл
Вт 26 декабря 2017 г. 8:50 утра
У меня не было много времени, чтобы посмотреть на обнаружение металлов с помощью чертеже Детектор металлов индукции импульсного индукции.

На тему усилителей звука для управления катушкой, индукционного детектора баланса, я задавался вопросом, может ли одна из этих маленьких досок усилителей класса D сделать уловку. Класс D теоретически более эффективен, что является большим соображением, если они работают из батарей. Они также представляют собой отдельные управляющие устройства, которые упрощают источник питания.

Ищите eBay для "DC 5V PAM8403 Class D" (также PAM8406, который может водить 5 Вт в 2 Ом при 5V) для той вещи, о которой я говорю.

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

На форуме есть несколько других тем о детекторах металлов, не уверен, как далеко эти люди удалось получить.
Мне интересно посмотреть, как твоя идея выходит. : D

Тед
Вторник 26 декабря 2017 г. 15:51
Результаты не теория, а фактические испытания, катушки могут быть такими же, как в оригинальном дизайне.
Я жду прибытия доски Arduino, так же, как DC42, однако, STM32103 даст лучшие результаты, это намного быстрее.

Тед
Вт 26 декабря 2017 г., 18:27
DC42B.JPG
DC42B.JPG (222.98 киб) просмотрено 1216 раз

Тед
Вт 23 января 2018 г. 11:59
Просто генератор сигналов +TDA2030 +осциллограф = 70 см.
Помощь в программе приветствуется.

Изображение

Дэнниф
Вт 23 января 2018 г. 13:05
это зависит от диапазона желаемого обнаружения.

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

Это обнаружение может быть сделано путем сравнения частоты против. внутренний генератор, или Xtal, .... Наиболее интересным случаем является настройка катушки + металл в качестве основного генератора и использовать другие осцилляторы на борту, например, время -аут, чтобы обнаружить сдвиг частоты....

Смиренного аттини здесь более чем достаточно.

Тед
Вт 23 января 2018 г. 13:42
Моя цель - обнаружить Cola Can с расстояния 1m+, нет проблем с катушкой
нулевая. Упомянутый метод измерение сдвига частоты намного чувствителен к LES, чем детекторы TX-RX.

Дэнниф
Вторник 23 января 2018 г. 15:27
Кола может с расстояния 1M+ Вы можете помочь себе, установив реалистичные цели по дизайну и понимая, как обнаружение металла работает на некоторых металлах, таких как алюминий.

Пито
Вторник 23 января 2018 г., 17:15
Это зависит от того, поступает ли банка от нас или из Европы.. Два разных сплава, я думаю..

Тед
Вторник 23 января 2018 г. 18:09
Привет, пито, приятно видеть тебя здесь
На банке это говорит - Канада. Я заказал atmega328p на Aliexpress с ним, я ожидаю 1 м, всего на 30 см больше. С STM32 было бы лучше, но необходимо преобразовать код из AVR в ARM.

Тед
Вторник 30 января 2018 г. 14:00
Итак, я получил UNO, но у меня есть проблема с LCD 128x64 7920.
http: // hobbycomponents.com/изображения/форум ... 00_600.JPG

#1 код This is what I an using and Have nathing on LCD. #include // recommended by author DC42 // Digital pin definitions // Digital pin 0 not used, however if we are using the serial port for debugging then it's serial input const int debugTxPin = 1; // transmit pin reserved for debugging const int encoderButtonPin = 2; // encoder button, also IN0 for waking up from sleep mode const int earpiecePin = 3; // earpiece, aka OCR2B for tone generation const int T0InputPin = 4; const int coilDrivePin = 5; const int LcdRsPin = 6; const int LcdEnPin = 7; const int LcdRWPin = 0;[b] // added by me for testing [/b][color=#FF0000][/color] const int LcdPowerPin = 8; // LCD power and backlight enable const int T0OutputPin = 9; const int lcdD0Pin = 10; const int lcdD1Pin = 11; // pins 11-13 also used for ICSP const int LcdD2Pin = 12; const int LcdD3Pin = 13;

Беннебой
Вторник 30 января 2018 г. 14:55
Я думаю, что вам нужен штифт GPIO для ЖК -R/W. PIN 0 на Arduino Uno - серийный RX.

Чтобы упростить жизнь, я использую драйвер I2C LCD, меньше требуемых контактов, а библиотека - это падение замены, см. ЖК -код в этом репо -> https: // github.com/bennehboy/td5ecuemulator

Тед
Вторник 30 января 2018 г. 15:37
Я сделал это до без успеха const int lcdrwpin = 0; // добавлено мной для тестирования

Беннебой
Вторник 30 января 2018 г. 16:13
[Тед - Вторник 30 января 2018 г. 15:37] - Я сделал это до без успеха const int lcdrwpin = 0; // добавлено мной для тестирования


Сделал то, что раньше?

Я говорю, не используй PIN -код 0.

Тед
Вторник 30 января 2018 г. 16:37
Я пытаюсь использовать 0 пин, я попробую другие.

Тед
Ср 31 января 2018 12:49
Я думаю, что проблема описана ниже
У меня есть программа, которая имеет описание и сообщение с ЖК -плана. Итак, я добавляю жидкий лицистал.H Библиотека.
Я думаю, что я должен объявить тип использованного ЖК -дисплея и добавить команду для запуска ЖК -программы.
Что мне следует с булавками R/W и PBS ?

Ахулл
Ср 31 января 2018 г. 14:41
Я абсолютно ничего не знаю об этом конкретном дисплее, но из шелковидного экрана я предлагаю вам вытащить R/W Высокий, чтобы читать с дисплея, и низко, чтобы написать на него (поскольку стержень над W). Теперь, какая булавка вы выбрали, чтобы использовать это, я оставлю вас полностью.

Беннебой
Ср 31 января 2018 г. 15:07
http: // форум.хоббикомпоненты.com/viewto ... = 75&t = 1395

Смотрите выше, это устройство SPI....

Тед
Ср 31 января 2018 г. 15:23
я был там
Так что я тестирую свой ЖК -дисплей с традиционным «Hello World», работает ОК, эта программа использует различную ЖК -библиотеку и булавки.
#2 код
Код: выберите все
#include "u8glib.час"
// PINS ИСПОЛЬЗОВАНИЕ_ E, R/W, RS, PSB.

Беннебой
Ср 31 января 2018 г., 19:15
Последний пост от меня здесь....

Прочитайте ссылку, которую я опубликовал.... Установите UNO только с помощью LCD, подключенного с использованием контактов, описанных в ссылке. Скомпилируйте и загрузите тестовый эскиз, который они предоставляют.

Тед
Чт, 01 февраля 2018 г. 2:09
Я использовал последнюю ссылку, у меня есть «компоненты хобби» в кадрах. Как внедрить его в эту программу DC42 ?
#define TIMER1_TOP (249) // can adjust this to fine-tune the frequency to get the coil tuned (see above) #define USE_3V3_AREF (1) // set to 1 of running on an Arduino with USB power, 0 for an embedded atmega28p with no 3.3V supply available // Digital pin definitions // Digital pin 0 not used, however if we are using the serial port for debugging then it's serial input const int debugTxPin = 1; // transmit pin reserved for debugging const int encoderButtonPin = 2; // encoder button, also IN0 for waking up from sleep mode const int earpiecePin = 3; // earpiece, aka OCR2B for tone generation const int T0InputPin = 4; const int coilDrivePin = 5; const int LcdRsPin = 6; const int LcdEnPin = 7; const int LcdPowerPin = 8; // LCD power and backlight enable const int T0OutputPin = 9; const int lcdD0Pin = 10; const int lcdD1Pin = 11; // pins 11-13 also used for ICSP const int LcdD2Pin = 12; const int LcdD3Pin = 13; // Analog pin definitions const int receiverInputPin = 0; const int encoderAPin = A1; const int encoderBpin = A2; // Analog pins 3-5 not used // Variables used only by the ISR int16_t bins[4]; // bins used to accumulate ADC readings, one for each of the 4 phases uint16_t numSamples = 0; const uint16_t numSamplesToAverage = 1024; // Variables used by the ISR and outside it volatile int16_t averages[4]; // when we've accumulated enough readings in the bins, the ISR copies them to here and starts again volatile uint32_t ticks = 0; // system tick counter for timekeeping volatile bool sampleReady = false; // indicates that the averages array has been updated // Variables used only outside the ISR int16_t calib[4]; // values (set during calibration) that we subtract from the averages volatile uint8_t lastctr; volatile uint16_t misses = 0; // this counts how many times the ISR has been executed too late. Should remain at zero if everything is working properly. const double halfRoot2 = sqrt(0.5); const double quarterPi = 3.1415927/4.0; const double radiansToDegrees = 180.0/3.1415927; // The ADC sample and hold occurs 2 ADC clocks (= 32 system clocks) after the timer 1 overflow flag is set. // This introduces a slight phase error, which we adjust for in the calculations. const float phaseAdjust = (45.0 * 32.0)/(float)(TIMER1_TOP + 1); float threshold = 10.0; // lower = greater sensitivity. 10 is just about usable with a well-balanced coil. // The user will be able to adjust this via a pot or rotary encoder. void setup() { pinMode(encoderButtonPin, INPUT_PULLUP); digitalWrite(T0OutputPin, LOW); pinMode(T0OutputPin, OUTPUT); // pulse pin from timer 1 used to feed timer 0 digitalWrite(coilDrivePin, LOW); pinMode(coilDrivePin, OUTPUT); // timer 0 output, square wave to drive transmit coil cli(); // Stop timer 0 which was set up by the Arduino core TCCR0B = 0; // stop the timer TIMSK0 = 0; // disable interrupt TIFR0 = 0x07; // clear any pending interrupt // Set up ADC to trigger and read channel 0 on timer 1 overflow #if USE_3V3_AREF ADMUX = (1 << ADLAR); // use AREF pin (connected to 3.3V) as voltage reference, read pin A0, left-adjust result #else ADMUX = (1 << REFS0) | (1 << ADLAR); // use Avcc as voltage reference, read pin A0, left-adjust result #endif ADCSRB = (1 << ADTS2) | (1 << ADTS1); // auto-trigger ADC on timer/counter 1 overflow ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADPS2); // enable adc, enable auto-trigger, prescaler = 16 (1MHz ADC clock) DIDR0 = 1; // Set up timer 1. // Prescaler = 1, phase correct PWM mode, TOP = ICR1A TCCR1A = (1 << COM1A1) | (1 << WGM11); TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS10); // CTC mode, prescaler = 1 TCCR1C = 0; OCR1AH = (TIMER1_TOP/2 >> 8); OCR1AL = (TIMER1_TOP/2 & 0xFF); ICR1H = (TIMER1_TOP >> 8); ICR1L = (TIMER1_TOP & 0xFF); TCNT1H = 0; TCNT1L = 0; TIFR1 = 0x07; // clear any pending interrupt TIMSK1 = (1 << TOIE1); // Set up timer 0 // Clock source = T0, fast PWM mode, TOP (OCR0A) = 7, PWM output on OC0B TCCR0A = (1 << COM0B1) | (1 << WGM01) | (1 << WGM00); TCCR0B = (1 << CS00) | (1 << CS01) | (1 << CS02) | (1 << WGM02); OCR0A = 7; OCR0B = 3; TCNT0 = 0; sei(); while (!sampleReady) {} // discard the first sample misses = 0; sampleReady = false; Serial.begin(19200); } // Timer 0 overflow interrupt. This serves 2 purposes: // 1. It clears the timer 0 overflow flag. If we don't do this, the ADC will not see any more Timer 0 overflows and we will not get any more conversions. // 2. It increments the tick counter, allowing is to do timekeeping. We get 62500 ticks/second. // We now read the ADC in the timer interrupt routine instead of having a separate comversion complete interrupt. ISR(TIMER1_OVF_vect) { ++ticks; uint8_t ctr = TCNT0; int16_t val = (int16_t)(uint16_t)ADCH; // only need to read most significant 8 bits if (ctr != ((lastctr + 1) & 7)) { ++misses; } lastctr = ctr; int16_t *p = &bins[ctr & 3]; if (ctr < 4) { *p += (val); if (*p > 15000) *p = 15000; } else { *p -= val; if (*p < -15000) *p = -15000; } if (ctr == 7) { ++numSamples; if (numSamples == numSamplesToAverage) { numSamples = 0; if (!sampleReady) // if previous sample has been consumed { memcpy((void*)averages, bins, sizeof(averages)); sampleReady = true; } memset(bins, 0, sizeof(bins)); } } } void loop() { while (!sampleReady) {} uint32_t oldTicks = ticks; if (digitalRead(encoderButtonPin) == LOW) { // Calibrate button pressed. We save the current phase detector outputs and subtract them from future results. // This lets us use the detector if the coil is slightly off-balance. // It would be better to everage several samples instead of taking just one. for (int i = 0; i < 4; ++i) { calib[i] = averages[i]; } sampleReady = false; Serial.print("Calibrated: "); for (int i = 0; i < 4; ++i) { Serial.write(' '); Serial.print(calib[i]); } Serial.println(); } else { for (int i = 0; i < 4; ++i) { averages[i] -= calib[i]; } const double f = 200.0; // Massage the results to eliminate sensitivity to the 3rd harmonic, and divide by 200 double bin0 = (averages[0] + halfRoot2 * (averages[1] - averages[3]))/f; double bin1 = (averages[1] + halfRoot2 * (averages[0] + averages[2]))/f; double bin2 = (averages[2] + halfRoot2 * (averages[1] + averages[3]))/f; double bin3 = (averages[3] + halfRoot2 * (averages[2] - averages[0]))/f; sampleReady = false; // we've finished reading the averages, so the ISR is free to overwrite them again double amp1 = sqrt((bin0 * bin0) + (bin2 * bin2)); double amp2 = sqrt((bin1 * bin1) + (bin3 * bin3)); double ampAverage = (amp1 + amp2)/2.0; // The ADC sample/hold takes place 2 clocks after the timer overflow double phase1 = atan2(bin0, bin2) * radiansToDegrees + 45.0; double phase2 = atan2(bin1, bin3) * radiansToDegrees; if (phase1 > phase2) { double temp = phase1; phase1 = phase2; phase2 = temp; } double phaseAverage = ((phase1 + phase2)/2.0) - phaseAdjust; if (phase2 - phase1 > 180.0) { if (phaseAverage < 0.0) { phaseAverage += 180.0; } else { phaseAverage -= 180.0; } } // For diagnostic purposes, print the individual bin counts and the 2 indepedently-calculated gains and phases Serial.print(misses); Serial.write(' '); if (bin0 >= 0.0) Serial.write(' '); Serial.print(bin0, 2); Serial.write(' '); if (bin1 >= 0.0) Serial.write(' '); Serial.print(bin1, 2); Serial.write(' '); if (bin2 >= 0.0) Serial.write(' '); Serial.print(bin2, 2); Serial.write(' '); if (bin3 >= 0.0) Serial.write(' '); Serial.print(bin3, 2); Serial.print(" "); Serial.print(amp1, 2); Serial.write(' '); Serial.print(amp2, 2); Serial.write(' '); if (phase1 >= 0.0) Serial.write(' '); Serial.print(phase1, 2); Serial.write(' '); if (phase2 >= 0.0) Serial.write(' '); Serial.print(phase2, 2); Serial.print(" "); // Print the final amplitude and phase, which we use to decide what (if anything) we have found) if (ampAverage >= 0.0) Serial.write(' '); Serial.print(ampAverage, 1); Serial.write(' '); if (phaseAverage >= 0.0) Serial.write(' '); Serial.print((int)phaseAverage); // Decide what we have found and tell the user if (ampAverage >= threshold) { // When held in line with the centre of the coil: // - non-ferrous metals give a negative phase shift, e.g. -90deg for thick copper or aluminium, a copper olive, -30deg for thin alumimium. // Ferrous metals give zero phase shift or a small positive phase shift. // So we'll say that anything with a phase shift below -20deg is non-ferrous. if (phaseAverage < -20.0) { Serial.print(" Non-ferrous"); } else { Serial.print(" Ferrous"); } float temp = ampAverage; while (temp > threshold) { Serial.write('!'); temp -= (threshold/2); } } Serial.println(); } while (ticks - oldTicks < 16000) { } }

Тед
Чт, 01 февраля 2018 г., 3:27
Я сделал две реализации, экран черный для программы DC42, и для программы «Hello World» работает.
Поэтому мне нужно изменить черный экран, чтобы отобразить сообщение программы DC42, которые находятся на своем конце = активировать последовательный.печать


#1 // include the library code: //#include /* Include the U8glib library */ #include "U8glib.h" /* Define the SPI Chip Select pin */ #define CS_PIN 10 /* Create an instance of the library for the 12864 LCD in SPI mode */ U8GLIB_ST7920_128X64_1X u8g(CS_PIN);

Беннебой
Чт 01 февраля 2018 г. 8:09
Я подозреваю, что вам может быть лучше, задавая ваши вопросы об arduino.Форум CC, который имеет гораздо более активное USRE, со временем, чтобы помочь новичкам в кодировании AVR/MCU - в соответствии с вопросами, которые вы задаете, действительно не связаны с STM32, в то время как вы выясняете, как получить основы вашего проекта, работая над UNO.

Тед
Чт 01 февраля 2018 г., 20:47
ЖК -дисплей отображает то, что находится под прямой линией № 1, мне нужно изменить это на информацию ниже.
// Induction balance metal detector // We run the CPU at 16MHz and the ADC clock at 1MHz. ADC resolution is reduced to 8 bits at this speed. // Timer 1 is used to divide the system clock by about 256 to produce a 62.5kHz square wave. // This is used to drive timer 0 and also to trigger ADC conversions. // Timer 0 is used to divide the output of timer 1 by 8, giving a 7.8125kHz signal for driving the transmit coil. // This gives us 16 ADC clock cycles for each ADC conversion (it actually takes 13.5 cycles), and we take 8 samples per cycle of the coil drive voltage. // The ADC implements four phase-sensitive detectors at 45 degree intervals. Using 4 instead of just 2 allows us to cancel the third harmonic of the // coil frequency. // Timer 2 will be used to generate a tone for the earpiece or headset. // Other division ratios for timer 1 are possible, from about 235 upwards. // Wiring: // Connect digital pin 4 (alias T0) to digital pin 9 // Connect digital pin 5 through resistor to primary coil and tuning capacitor // Connect output from receive amplifier to analog pin 0. Output of receive amplifier should be biased to about half of the analog reference. // When using USB power, change analog reference to the 3.3V pin, because there is too much noise on the +5V rail to get good sensitivity. #define TIMER1_TOP (249) // can adjust this to fine-tune the frequency to get the coil tuned (see above) #define USE_3V3_AREF (1) // set to 1 of running on an Arduino with USB power, 0 for an embedded atmega28p with no 3.3V supply available // include the library code: //#include /* Include the U8glib library */ #include "U8glib.h" /* Define the SPI Chip Select pin */ #define CS_PIN 10 /* Create an instance of the library for the 12864 LCD in SPI mode */ U8GLIB_ST7920_128X64_1X u8g(CS_PIN); // initialize the library by associating any needed LCD interface pin // with the arduino pin number it is connected to //const int rs = 6, en = 7, d4 = 10, d5 = 11, d6 = 12, d7 = 13; //LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // Digital pin definitions // Digital pin 0 not used, however if we are using the serial port for debugging then it's serial input const int debugTxPin = 1; // transmit pin reserved for debugging const int encoderButtonPin = 2; // encoder button, also IN0 for waking up from sleep mode const int earpiecePin = 3; // earpiece, aka OCR2B for tone generation const int T0InputPin = 4; const int coilDrivePin = 5; const int LcdEPin = 13; const int LcdRWPin = 11; const int LcdRsPin = 10; //const int LcdRsPin = 6; //const int LcdEnPin = 7; const int LcdPowerPin = 8; // LCD power and backlight enable const int T0OutputPin = 9; /* const int lcdD0Pin = 10; const int lcdD1Pin = 11; // pins 11-13 also used for ICSP const int LcdD2Pin = 12; const int LcdD3Pin = 13; */ // Analog pin definitions const int receiverInputPin = 0; const int encoderAPin = A1; const int encoderBpin = A2; // Analog pins 3-5 not used // Variables used only by the ISR int16_t bins[4]; // bins used to accumulate ADC readings, one for each of the 4 phases uint16_t numSamples = 0; const uint16_t numSamplesToAverage = 1024; // Variables used by the ISR and outside it volatile int16_t averages[4]; // when we've accumulated enough readings in the bins, the ISR copies them to here and starts again volatile uint32_t ticks = 0; // system tick counter for timekeeping volatile bool sampleReady = false; // indicates that the averages array has been updated // Variables used only outside the ISR int16_t calib[4]; // values (set during calibration) that we subtract from the averages volatile uint8_t lastctr; volatile uint16_t misses = 0; // this counts how many times the ISR has been executed too late. Should remain at zero if everything is working properly. const double halfRoot2 = sqrt(0.5); const double quarterPi = 3.1415927/4.0; const double radiansToDegrees = 180.0/3.1415927; // The ADC sample and hold occurs 2 ADC clocks (= 32 system clocks) after the timer 1 overflow flag is set. // This introduces a slight phase error, which we adjust for in the calculations. const float phaseAdjust = (45.0 * 32.0)/(float)(TIMER1_TOP + 1); float threshold = 10.0; // lower = greater sensitivity. 10 is just about usable with a well-balanced coil. // The user will be able to adjust this via a pot or rotary encoder. void setup() { // set up the LCD's number of columns and rows: // lcd.begin(16, 2); // Print a message to the LCD. //lcd.print("hello, world!"); /////////////////////////////////////////////////////////////// { /* Start of a picture loop */ u8g.firstPage(); /* Keep looping until finished drawing screen */ do { /* Set the font */ u8g.setFont(u8g_font_courB14); // #1 /////////////////////////////////////////////////////////// /* Display some text */ u8g.drawStr( 35, 26, "HOBBY"); u8g.drawStr( 8, 46, "COMPONENTS"); /* Draw a simple border */ u8g.drawFrame(5,5,117,54); u8g.drawFrame(3,3,121,58); }while(u8g.nextPage()); } pinMode(encoderButtonPin, INPUT_PULLUP); digitalWrite(T0OutputPin, LOW); pinMode(T0OutputPin, OUTPUT); // pulse pin from timer 1 used to feed timer 0 digitalWrite(coilDrivePin, LOW); pinMode(coilDrivePin, OUTPUT); // timer 0 output, square wave to drive transmit coil cli(); // Stop timer 0 which was set up by the Arduino core TCCR0B = 0; // stop the timer TIMSK0 = 0; // disable interrupt TIFR0 = 0x07; // clear any pending interrupt // Set up ADC to trigger and read channel 0 on timer 1 overflow #if USE_3V3_AREF ADMUX = (1 << ADLAR); // use AREF pin (connected to 3.3V) as voltage reference, read pin A0, left-adjust result #else ADMUX = (1 << REFS0) | (1 << ADLAR); // use Avcc as voltage reference, read pin A0, left-adjust result #endif ADCSRB = (1 << ADTS2) | (1 << ADTS1); // auto-trigger ADC on timer/counter 1 overflow ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADPS2); // enable adc, enable auto-trigger, prescaler = 16 (1MHz ADC clock) DIDR0 = 1; // Set up timer 1. // Prescaler = 1, phase correct PWM mode, TOP = ICR1A TCCR1A = (1 << COM1A1) | (1 << WGM11); TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS10); // CTC mode, prescaler = 1 TCCR1C = 0; OCR1AH = (TIMER1_TOP/2 >> 8); OCR1AL = (TIMER1_TOP/2 & 0xFF); ICR1H = (TIMER1_TOP >> 8); ICR1L = (TIMER1_TOP & 0xFF); TCNT1H = 0; TCNT1L = 0; TIFR1 = 0x07; // clear any pending interrupt TIMSK1 = (1 << TOIE1); // Set up timer 0 // Clock source = T0, fast PWM mode, TOP (OCR0A) = 7, PWM output on OC0B TCCR0A = (1 << COM0B1) | (1 << WGM01) | (1 << WGM00); TCCR0B = (1 << CS00) | (1 << CS01) | (1 << CS02) | (1 << WGM02); OCR0A = 7; OCR0B = 3; TCNT0 = 0; sei(); while (!sampleReady) {} // discard the first sample misses = 0; sampleReady = false; Serial.begin(19200); } // Timer 0 overflow interrupt. This serves 2 purposes: // 1. It clears the timer 0 overflow flag. If we don't do this, the ADC will not see any more Timer 0 overflows and we will not get any more conversions. // 2. It increments the tick counter, allowing is to do timekeeping. We get 62500 ticks/second. // We now read the ADC in the timer interrupt routine instead of having a separate comversion complete interrupt. ISR(TIMER1_OVF_vect) { ++ticks; uint8_t ctr = TCNT0; int16_t val = (int16_t)(uint16_t)ADCH; // only need to read most significant 8 bits if (ctr != ((lastctr + 1) & 7)) { ++misses; } lastctr = ctr; int16_t *p = &bins[ctr & 3]; if (ctr < 4) { *p += (val); if (*p > 15000) *p = 15000; } else { *p -= val; if (*p < -15000) *p = -15000; } if (ctr == 7) { ++numSamples; if (numSamples == numSamplesToAverage) { numSamples = 0; if (!sampleReady) // if previous sample has been consumed { memcpy((void*)averages, bins, sizeof(averages)); sampleReady = true; } memset(bins, 0, sizeof(bins)); } } } void loop() { while (!sampleReady) {} uint32_t oldTicks = ticks; if (digitalRead(encoderButtonPin) == LOW) { // Calibrate button pressed. We save the current phase detector outputs and subtract them from future results. // This lets us use the detector if the coil is slightly off-balance. // It would be better to everage several samples instead of taking just one. for (int i = 0; i < 4; ++i) { calib[i] = averages[i]; } sampleReady = false; Serial.print("Calibrated: "); for (int i = 0; i < 4; ++i) { Serial.write(' '); Serial.print(calib[i]); } Serial.println(); } else { for (int i = 0; i < 4; ++i) { averages[i] -= calib[i]; } const double f = 200.0; // Massage the results to eliminate sensitivity to the 3rd harmonic, and divide by 200 double bin0 = (averages[0] + halfRoot2 * (averages[1] - averages[3]))/f; double bin1 = (averages[1] + halfRoot2 * (averages[0] + averages[2]))/f; double bin2 = (averages[2] + halfRoot2 * (averages[1] + averages[3]))/f; double bin3 = (averages[3] + halfRoot2 * (averages[2] - averages[0]))/f; sampleReady = false; // we've finished reading the averages, so the ISR is free to overwrite them again double amp1 = sqrt((bin0 * bin0) + (bin2 * bin2)); double amp2 = sqrt((bin1 * bin1) + (bin3 * bin3)); double ampAverage = (amp1 + amp2)/2.0; // The ADC sample/hold takes place 2 clocks after the timer overflow double phase1 = atan2(bin0, bin2) * radiansToDegrees + 45.0; double phase2 = atan2(bin1, bin3) * radiansToDegrees; if (phase1 > phase2) { double temp = phase1; phase1 = phase2; phase2 = temp; } double phaseAverage = ((phase1 + phase2)/2.0) - phaseAdjust; if (phase2 - phase1 > 180.0) { if (phaseAverage < 0.0) { phaseAverage += 180.0; } else { phaseAverage -= 180.0; } } //#2 ////////////////////////////////////////////////////////////////////////////// // For diagnostic purposes, print the individual bin counts and the 2 indepedently-calculated gains and phases Serial.print(misses); Serial.write(' '); if (bin0 >= 0.0) Serial.write(' '); Serial.print(bin0, 2); Serial.write(' '); if (bin1 >= 0.0) Serial.write(' '); Serial.print(bin1, 2); Serial.write(' '); if (bin2 >= 0.0) Serial.write(' '); Serial.print(bin2, 2); Serial.write(' '); if (bin3 >= 0.0) Serial.write(' '); Serial.print(bin3, 2); Serial.print(" "); Serial.print(amp1, 2); Serial.write(' '); Serial.print(amp2, 2); Serial.write(' '); if (phase1 >= 0.0) Serial.write(' '); Serial.print(phase1, 2); Serial.write(' '); if (phase2 >= 0.0) Serial.write(' '); Serial.print(phase2, 2); Serial.print(" "); // Print the final amplitude and phase, which we use to decide what (if anything) we have found) if (ampAverage >= 0.0) Serial.write(' '); Serial.print(ampAverage, 1); Serial.write(' '); if (phaseAverage >= 0.0) Serial.write(' '); Serial.print((int)phaseAverage); // Decide what we have found and tell the user if (ampAverage >= threshold) { // When held in line with the centre of the coil: // - non-ferrous metals give a negative phase shift, e.g. -90deg for thick copper or aluminium, a copper olive, -30deg for thin alumimium. // Ferrous metals give zero phase shift or a small positive phase shift. // So we'll say that anything with a phase shift below -20deg is non-ferrous. if (phaseAverage < -20.0) { Serial.print(" Non-ferrous"); } else { Serial.print(" Ferrous"); } float temp = ampAverage; while (temp > threshold) { Serial.write('!'); temp -= (threshold/2); } } Serial.println(); } while (ticks - oldTicks < 16000) { } }

Mrburnette
Чт, 01 февраля 2018 г., 22:41
[Беннебой - Чт 01 февраля 2018 г. 8:09 утра] - Я подозреваю ...
Я думаю, что Тед просто держит нас в курсе своего прогресса .. Как журнал проекта.

Луча

Тед
Пт, 02 февраля 2018 г., 15:44
Тед изучает программирование.
Он показывает, с какими проблемами он сталкивается, и ищет на них ответы.

Tfried
Сб 03 февраля 2018 г. 20:06
Тед изучает программирование.
Он показывает, с какими проблемами он сталкивается, и ищет на них ответы.
Нет проблем, Тед. Мы все были там, C ++ не является чем -то родным языком, в конце концов.

Но при поиске ответов примите, когда ответ: «Вам нужно сделать шаг назад и начать базовый". Действительно, вы пытаетесь решить конкретные проблемы, и, конечно, найти решение этих проблем, именно поэтому вы смотрите на программирование в первую очередь. Но даже если вы можете чувствовать себя очень близко к решению этих проблем с вашим текущим методом копирования и вставки, вы, кажется, полностью недооценивают, это ваше отсутствие понимания справедливого как Любое из того, что на самом деле работает ваше копирование (на уровне программирования). Извините, но в этом не хватает является фундаментальным И вы нигде не пытаетесь игнорировать это. Лучшее понимание будет нет Приходите автоматически, просто потратив больше времени на свой подход. Вместо этого, что вам нужно сделать, это вернуться и проработать некоторые основные учебные пособия. Сосредоточившись на "Hello World!"Может выглядеть как огромный шаг назад, но вы ни разу Собираюсь достичь ваших реальных целей, если вы не потратите время на понимание каждая линия таких основных примеров. Да, многое из этого уже будет вам знакомо. Не позволяй этому обмануть тебя. Вам все еще нужно понять основы, полностью.

Поскольку вы говорите, что у вас есть твердое сцепление со стороны электроники, и вам не нужна помощь с такими основными задачами, как установка или загрузка, попробуйте эти учебники, сосредоточенные на основе программирования: https: // startelectronics.org/softwar ... Am-Course/. Все они, пожалуйста. И опять же, вам нужно понять каждую линию кода в этих учебниках. Это займет некоторое время (хотя не навсегда) и усилия (не усилие супергероя), но нет ярлыка Чтобы изучить основы.

Ваше здоровье!

Тед
Сб 03 февраля 2018 г., 20:29
Я мечтаю понять каждую строку, спасибо за отличную ссылку, я близок, чтобы решить проблему, просто заменить сериал на ЖК -дисплей и больше копать.

Тед
Чт, 08 февраля 2018 г. 14:43
Я следил за тем, чтобы добраться до кока -колы - 95 см. Не нужен фильтр наемка 60 Гц
Программа любой информации ценится.

Ахулл
Сб 10 февраля 2018 г. 12:29
Насколько хороша ваша тригонометрия Foo?

https: // www.Researchgate.net/post/how_t ... tch_filter

Я предполагаю, что вы пытаетесь удалить Главные гули, Но вы не полностью описали свою проблему. Вам может быть проще сделать фильтрацию с одним или несколькими электронными фильтрами R/C или L/C. Это займет часть нагрузки с вашего процессора. Иногда проще бросить несколько операционных усилий и некоторых пассива в задачу, чем попытаться вычислить решение в режиме реального времени. Тем более.

https: // en.Википедия.org/wiki/band-stop_filter

Ахулл
Сб 10 февраля 2018 г. 11:30
Связанный (своего рода) -> https: // chackaday.com/2018/02/10/all- ... id-to-ask/



Связано в том смысле, что эта серия видео сообщает вам в относительно усваиваемом формате * Как * удаление определенной частоты из кучи частот на самом деле работает.

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



Также прочитание этого связанного потока... -> ViewTopic.PHP?t = 1145&начало = 30#p14677
... И видео здесь ...





Может быть, тоже стоит время.

Пито
Сб 10 февраля 2018 г. 13:53
60 Гц Band Stop:
С помощью фильтра FIR вы можете получить, например, (нажмите «Исходный код», выберите IE. Формат числа: целое число и 32 -битный int precision и скопировать/вставить источник) - ссылка находится на рисунке ниже:
60 Гц bandstop_minus 90db.jpg
60 Гц bandstop_minus 90db.JPG (85.54 киб) просмотрено 309 раз

Ахулл
Сб 10 февраля 2018 г. 14:13
Очень аккуратно. Мне это нравится. (Ссылка на вышеупомянутый сайт -> здесь <- )

Пито
Сб 10 февраля 2018 г. 15:22
.. #include "SampleFilter.c" .. int32_t signal; // the actual ADC signal sample int32_t fsig; // internal FIR filter variable setup() { .. SampleFilter_init(&fsig); // you have to init the FIR filter .. } HERE IS A 400Hz SAMPLING LOOP >>>>> signal = readAnalog(PA4); // get 12bit signal sample SampleFilter_put(&fsig, signal); // pass the signal into the FIR filter signal = SampleFilter_get(&fsig); // read the signal from the FIR filter .. DO SOMETHING WITH THE FILTERED signal .. <<<<< END OF THE 400Hz SAMPLING LOOP

Тед
Сб 10 февраля 2018 г. 16:02
Спасибо за вашу поддержку, я читаю всю информацию, я могу сгенерировать исходный код для фильтров, но я еще не знаю, как их реализовать, я имею в виду добавить функции для выводов ввода и вывода.
Вот код, который работал раньше, но когда я его сохранил и снова открыл, ШИМ на PIN PB1 больше нет. В этой программе также Notch Filter.
#include #include const float ECG_samplefreq = 360; const uint8_t ECG_pin = PB0; const int16_t DC_offset = 511; //const uint8_t ECG_pin = PB1; //output pin int outputPin = PB1; //output pin //int outputPin = PA6; //output pin // 50 Hz notch //const float b_notch[] = { 1.39972748302835, -1.79945496605670, 1.39972748302835 }; /* // 35 Hz Butterworth low-pass const float b_lp[] = { 0.00113722762905776, 0.00568613814528881, 0.0113722762905776, 0.0113722762905776, 0.00568613814528881, 0.00113722762905776 }; const float a_lp[] = { 1, -3.03124451613593, 3.92924380774061, -2.65660499035499, 0.928185738776705, -0.133188755896548 }; */ const float a_coefficients[] = {1, 3.610968072739773, 5.096060175734044, 3.317095275389235, 0.844114606367055}; const float b_coefficients[] = {0.003306153133358, 0, -0.006612306266715, 0, 0.003306153133358}; /* // 0.3 Hz high-pass const float b_hp[] = { 1, -1 }; const float a_hp[] = { 1, -0.995 }; FIRFilter notch(b_notch); //IIRFilter lp(b_lp, a_lp); IIRFilter hp(b_hp, a_hp); */ void setup() { Serial.begin(115200); } unsigned long ECG_prevmicros = micros(); void loop() { const static unsigned long ECG_interval = round(1e6 / ECG_samplefreq); if (!Serial) { ECG_prevmicros = micros(); } else if (micros() - ECG_prevmicros >= ECG_interval) { measureECGAndSend(); ECG_prevmicros += ECG_interval; } } void measureECGAndSend() { int16_t value = analogRead(ECG_pin); float filtered = //notch.filter( //lp.filter( // hp.filter(value - DC_offset)); value = round((filtered) + DC_offset); Serial.println(value); //Serial.print(value); // PWM on PB1 value = map(value, 0, 1023, 0, 255); value = constrain(value, 0, 255); analogWrite(outputPin, value); // output pin }

Тед
Сб 10 февраля 2018 г. 20:05
Спасибо, Пито
Я прочитал все, включая ссылку, но со своими знаниями по программированию я не могу собрать все вместе.

[Решено] Проблема ILI9431