Как добавить LCD Display

Тед
Offline
Зарегистрирован: 06.11.2017

Может быть, кто-то знает, как добавить LCD Display в эту программу?

// 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

// 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)
  {
  }
}

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Тед пишет:

Может быть, кто-то знает, как добавить LCD Display в эту программу?

Ну, я, может быть, знаю. Тебе стало легче?

arduino328
Offline
Зарегистрирован: 01.09.2016

Ворота пишет:

Тед пишет:

Может быть, кто-то знает, как добавить LCD Display в эту программу?

Ну, я, может быть, знаю.

Я даже знаю как: молча! :)

5N62V
Offline
Зарегистрирован: 25.02.2016

Тед пишет:

Может быть, кто-то знает, как добавить LCD Display в эту программу?


Эта программа +  LCD Display. Так? 

Тед
Offline
Зарегистрирован: 06.11.2017

да

b707
Онлайн
Зарегистрирован: 26.05.2017

Тед, ну вы наверно уже все сами поняли? - если нет - перевожу: Никто здесь вставлять в ваш скетч дисплей не станет.

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

Если же ваша проблема - "ваще не знаю как написать" - то с этой бедой вам не сюда.

Тед
Offline
Зарегистрирован: 06.11.2017

Я добавил LCD 16X2 с программой «Hello World» . Теперь мне нужно это заменить  чтобы  ЛСД показывал  информацию находящейся   в конце программы, строки 237 - 297. Вот этого пока не знаю как сделать, помогите пожалуйста.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

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

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

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Тед пишет:

Я добавил LCD 16X2 с программой «Hello World» . Теперь мне нужно это заменить  чтобы  ЛСД показывал  информацию находящейся   в конце программы, строки 237 - 297. Вот этого пока не знаю как сделать, помогите пожалуйста.

Замени в этих строках "Serial" на "lcd", оно на дисплей и полезет.

А вот как это там разместить...

Придется изучить команду lcd.setCursor(x, y) и от чего-то отказаться.

P.S. Да и "Serial.write" замени на "lcd.print".

Тед
Offline
Зарегистрирован: 06.11.2017
Спасибо Алекс, вот что искал - замена на ...
С курсором разбираюсь.
Тед
Offline
Зарегистрирован: 06.11.2017

я сделал два исмения но <<hello world >> остался и ничего нового не появилась
#1 
  sampleReady = false;
   lcd.print("Calibrated: ");
    for (int i = 0; i < 4; ++i)
    {
      lcd.print(' ');
      lcd.print(calib[i]);
    }
   lcd.println();

#2

 // 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)
      {
       lcd.print(" Non-ferrous");
      }
      else
      {
        lcd.print(" Ferrous");
      }
      float temp = ampAverage;
      while (temp > threshold)
      {
       lcd.print('!');
        temp -= (threshold/2);
      }
    }   
   lcd.println();
   }
  while (ticks - oldTicks < 16000)
  {
  }
}

 

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Покажи целиком, с include и setup и прочим.

Тед
Offline
Зарегистрирован: 06.11.2017

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

 

// 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

//            #1 add
// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  // RS, E, D4, D5, D6, D7, LCD R/W pin to ground

LiquidCrystal lcd(13, 12, 6, 7, 10, 11);  // RS, E, 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 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


           // #2 add
   // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);  // set up the LCD’s number of columns and rows:

  
  // Print a message to the LCD.
  lcd.print("hello, 2 world!");

  
  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()
{


// #3 add
 // Turn off the display:
  lcd.noDisplay();
  delay(500);
  // Turn on the display:
  lcd.display();
  delay(500);


  
  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;
   lcd.print("Calibrated: ");
    for (int i = 0; i < 4; ++i)
    {
      lcd.print(' ');
      lcd.print(calib[i]);
    }
   lcd.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;
      }
    }

/*
 * Замени в этих строках "Serial" на "lcd", оно на дисплей и полезет.

А вот как это там разместить...

Придется изучить команду lcd.setCursor(x, y) и от чего-то отказаться.

P.S. Да и "Serial.write" замени на "lcd.print".Замени в этих строках "Serial" на "lcd", оно на дисплей и полезет.

А вот как это там разместить...

Придется изучить команду lcd.setCursor(x, y) и от чего-то отказаться.

P.S. Да и "Serial.write" замени на "lcd.print".
 */

        
    // For diagnostic purposes, print the individual bin counts and the 2 indepedently-calculated gains and phases                                                        
//11c
    
    // 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)
      {
       lcd.print(" Non-ferrous");
      }
      else
      {
        lcd.print(" Ferrous");
      }
      float temp = ampAverage;
      while (temp > threshold)
      {
       lcd.print('!');
        temp -= (threshold/2);
      }
    }   
   lcd.println();
   }
  while (ticks - oldTicks < 16000)
  {
  }
}

 

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Вот эту фигню:

// #3 add
198
 // Turn off the display:
199
  lcd.noDisplay();
200
  delay(500);
201
  // Turn on the display:
202
  lcd.display();
203
  delay(500);

Нужно убрать.

И написать туда lcd.clear ();

Тогда при нажатии кнопки энкодера должно в верхней строке писаться "Calibrated xxxx".

Тед
Offline
Зарегистрирован: 06.11.2017

строчки #26 и # 96 = #1 add и #2 аdd. Это я добавил для LCD 16ХХ2

Alex-GK
Offline
Зарегистрирован: 10.04.2012

№26 и №96 правильные строчки.

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Да, и 315 строку удалить нафиг, при выводе в сериал оно красоту наводит, а тут лишняя.

Тед
Offline
Зарегистрирован: 06.11.2017

убрал но ничего не изменилось,кнопка не работает


void loop()
{

/*
// #3 add
 // Turn off the display:
  lcd.noDisplay();
  delay(500);
  // Turn on the display:
  lcd.display();
  delay(500);
  */
lcd.clear ();

  
  while (!sampleReady) {}
  uint32_t oldTicks = ticks;

 

Тед
Offline
Зарегистрирован: 06.11.2017

убрал 315, тоже самое

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Т.е. пока было Serial всё работало, а как поменял на lcd так нифига?

Очень странно, не должно оно было сломаться. Единственная умная мысль продублировать сообщения и на Serial и на lcd.

И еще раз убедиться, что не работает только дисплей, а вывод в сериал работает.

Тед
Offline
Зарегистрирован: 06.11.2017

Отключил 

//lcd.print("hello, 2 world!");

на экране ничего нет, поищу.
Спасибо большое
Тед
Offline
Зарегистрирован: 06.11.2017

Alex-GK пишет:

Т.е. пока было Serial всё работало, а как поменял на lcd так нифига?

 

Все работает без изменений, одна программа другой не мешает

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Раз "Хелло ворд" выводился, значит дисплей подключен правильно и библиотека правильная и инициализация нормальная.

А вот раз не пишет ожидаемого значит или выполнение не попадает в это место или глюк какой-то.

Чтобы убедится, что нужное место выполняется нужно добавить туда дополнительный вывод в Сериал, если в сериал вылезет а на экран нет - будем думать.

Тед
Offline
Зарегистрирован: 06.11.2017
забыл перемычку << пин 9 и 4 >>, кнопка работает.
еще раз Спасибо Большое
Alex-GK
Offline
Зарегистрирован: 10.04.2012

Ну Ё-Ё-Ёжик! Таки всё заработало?

Тед
Offline
Зарегистрирован: 06.11.2017
Не знаю, подключу катушки посмотрю.
Пока  на ЛСД  только одна строчка показывает << calibrated:  0  0 >> во второй ничего пока  нет.
Alex-GK
Offline
Зарегистрирован: 10.04.2012

Чтобы пошло во вторую, перед выводом на экран нужно поставить lcd.setCursor (0,1);

Эта команда говорит : Выводить начина с первой позиции второй строки (нумерация позиций и строк идет с 0).

Тед
Offline
Зарегистрирован: 06.11.2017

В одной строке должно показывать то что показывает, во второй величину сдвига фазы - номерa

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Вот и воткни lcd.setCursor (0,1); прямо перед 300 строкой.

Тед
Offline
Зарегистрирован: 06.11.2017

Думаю что после нажатия кнопки во второй строчке должно быть 0 <<зеро> а когда появится сигнал от металла номера должны меница.

Тед
Offline
Зарегистрирован: 06.11.2017
   
Сделал так, но это должно быть в той же строке чо <<  kalibrated>>
во второй значение фазы 

lcd.setCursor (0,1);
if (phaseAverage < -20.0)
{
lcd.print(" Non-ferrous");
}
else
{
lcd.print(" Ferrous");
}
float temp = ampAverage;
while (temp > threshold)
{
lcd.print('!');
temp -= (threshold/2);
}
}

 

Тед
Offline
Зарегистрирован: 06.11.2017
Alex-GK
Offline
Зарегистрирован: 10.04.2012

В оригинальном скетче фазу выводили строки то-ли 257 и 260 то-ли 265 и 268, в переделанном я этих строк вообще не нахожу

Нужно их вернуть и вот перед ними и нужно lcd.setCursor (0,1);

А там где ты воткнул lcd.setCursor (0,1);, поменяй его на lcd.setCursor (0,0);

Тед
Offline
Зарегистрирован: 06.11.2017

Как они исчезли не знаю, начинаю всё с начала

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Удачи! Я - бухать. Если что - завтра отвечу.

Тед
Offline
Зарегистрирован: 06.11.2017

Спасибо, копаюсь

Тед
Offline
Зарегистрирован: 06.11.2017
После восстановления потерянных строчек на ЛСД имею
00xx45.00xxx0.0x
0xx0.00xx0.00xx0
x=ничего нет
 
Выключил эти строки
/*
    if (bin0 >= 0.0) lcd.print(' ');
    lcd.print(bin0, 2);
    lcd.print(' ');
    if (bin1 >= 0.0) lcd.print(' ');
    lcd.print(bin1, 2);
    lcd.print(' ');
    if (bin2 >= 0.0) lcd.print(' ');
    lcd.print(bin2, 2);
    lcd.print(' ');
    if (bin3 >= 0.0) lcd.print(' ');
    lcd.print(bin3, 2);
    lcd.print("  ");
*/
на ЛСД имею
xxxxxxxxxxxxxxx
0x0.00x0.00xx0.0
x=ничего нет
 
Мне вся информация не нужна, только значение амплитуды и фазы поэтому отключаю эти строчки.
 
LCD не реагирует на подачу сигнала на вход. Поменял 0 на А0 - не помогает
// Analog pin definitions
const int receiverInputPin = A0;

 

Тед
Offline
Зарегистрирован: 06.11.2017

исправил, ЛСД работает как надо А0 тоже, энкодер еще нет, дальше разбираюсь. 

  pinMode(encoderButtonPin, INPUT_PULLUP);  Не работает - нет  никакого напряжения

 

Тед
Offline
Зарегистрирован: 06.11.2017
никак не могу исправить строчку #89 - pinMode(encoderButtonPin, INPUT_PULLUP);
остальное почти работает
// 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

//            #1 add
// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  // RS, E, D4, D5, D6, D7, LCD R/W pin to ground

LiquidCrystal lcd(13, 12, 6, 7, 10, 11);  // RS, E, 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 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 = A0;
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


  // #2 add
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);  // set up the LCD’s number of columns and rows:


  // Print a message to the LCD.
  //lcd.print("hello, 2 world!");


  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()
{

  /*
    // #3 add
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
    delay(500);
  */

  lcd.clear ();
  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;
    lcd.print("Calibrated: ");
    for (int i = 0; i < 4; ++i)
    {
      lcd.print(' ');
      lcd.print(calib[i]);
    }
    // lcd.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;


    lcd.setCursor (0, 1);
    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
    //lcd.print(misses);
   // lcd.print(' ');
/*
    if (bin0 >= 0.0) lcd.print(' ');
    lcd.print(bin0, 2);
    lcd.print(' ');
    if (bin1 >= 0.0) lcd.print(' ');
    lcd.print(bin1, 2);
    lcd.print(' ');
    if (bin2 >= 0.0) lcd.print(' ');
    lcd.print(bin2, 2);
    lcd.print(' ');
    if (bin3 >= 0.0) lcd.print(' ');
    lcd.print(bin3, 2);
    lcd.print("  ");

    
    lcd.print(amp1, 2);
    lcd.print(' ');
    lcd.print(amp2, 2);
    lcd.print(' ');
    if (phase1 >= 0.0) lcd.print(' ');
    lcd.print(phase1, 2);
    lcd.print(' ');
    if (phase2 >= 0.0) lcd.print(' ');
    lcd.print(phase2, 2);
    lcd.print("  ");

*/

    // Print the final amplitude and phase, which we use to decide what (if anything) we have found)
    if (ampAverage >= 0.0) lcd.print(' ');
    lcd.print(ampAverage, 1);
    lcd.print(' ');
    if (phaseAverage >= 0.0) lcd.print(' ');
    lcd.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.

      lcd.setCursor (0, 0);
      if (phaseAverage < -20.0)


      {
       lcd.print(" N");
      }
      else
      {
        lcd.print(" F");
      }

      float temp = ampAverage;
      while (temp > threshold)
      {
        lcd.print('!');
        temp -= (threshold / 2);
      }
    }
    // Serial.println();
  }
  while (ticks - oldTicks < 16000)
  {
  }
}

 

Тед
Offline
Зарегистрирован: 06.11.2017

Вот подключил катушки 5 копеек обнаруживает с расстояния 25 см, но помехи мешают.У меня есть программа в которой находится режекторный фильтр на 50 гц , он работал раньше, плохо сохронил и ШИМ на PB1 исчез. Помогите пожалуйста.

 


#include <FIRFilter.h>
#include <IIRFilter.h>

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
}

 

Тед
Offline
Зарегистрирован: 06.11.2017
Alex
А переделал бы эту программу на заказ ?