Генератор для катушки "Мишина"

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

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

program.ino

// Генератор для катушки Мишина на основе DDS AD9833

/* 06.05.2022 
 *  - Переработал программу для 2-строчного экрана
 *
 * 11.06.2022 
 *  - Во время работы отключил возможность крутить время
 *  - В меня при работе изменил Таймре на Т, добавил знак V
 *  - Добавил всем пинам имя
 *  - Определил пины для потенциометра ...
 *  - Добавил управление потенциометром с помощью энкодера
 *  
 * 03.07.2022
 *  - перенес инициализацию потенциометра в начало setup 
 */
#define SECONDS(x) ((x) * 1000UL)
#define MINUTES(x)  (SECONDS(x) * 60UL)
#define HOURS(x)  (MINUTES(x) * 60UL)
#define DAYS(x)   (HOURS(x) * 24UL)
#define WEEKS(x)  (DAYS(x) * 7UL)
unsigned long interval = MINUTES(1);
unsigned long oneMinute = MINUTES(1);
unsigned long timers = MINUTES(5); // время таймера 15, 30, 45 или 60 минут
unsigned long memTimers=0; //здесь будем хранить установленное время таймера
unsigned long oldmemTimers=0;
byte isWorkStarted = 0; // флаг запуска таймера

unsigned long timMillis = 0;
unsigned long oldMillis = 0;
unsigned long mill; // переменная под millis()
unsigned long prevCorrectTime = 0;
unsigned long prevReadAnalogTime = 0; // для отсчета 10 секунд между подстройкой частоты
unsigned long prevUpdateDataIna = 0; // для перерыва между обновлениями данных ina

#include <Wire.h>
#include <SPI.h>

#include <LCD_1602_RUS.h>               // https://github.com/ssilver2007/LCD_1602_RUS
LCD_1602_RUS lcd(0x3F, 16, 2); // используемый дисплей (0x3F, 16, 2) адрес,символов в строке,строк.

#include "INA219.h"
INA219 ina219;

// PINS
#define CORRECT_PIN A7 // пин для внешней корректировки частоты.
#define ON_OFF_CASCADE_PIN 5 // для выключения выходного каскада
#define PIN_ENCODER1 6
#define PIN_ENCODER2 7
#define PIN_ENCODER3 3
#define PIN_ENCODER_BUTTON 8
#define PIN_ZUM 9  
#define PIN_FSYNC 10
// пины потенциометра
#define PIN_CS 4 
#define PIN_INC A1 
#define PIN_UD A2 

#define zFreq 2     // делитель интервала - секунда/2

unsigned int Data_ina219 = 0;

const int SINE = 0x2000;                    // определяем значение регистров AD9833 в зависимости от формы сигнала
// const int SQUARE = 0x2020;                  // После обновления частоты нужно определить форму сигнала
// const int TRIANGLE = 0x2002;                // и произвести запись в регистр.
const float refFreq = 25000000.0;           // Частота кристалла на плате AD9833

long FREQ_MIN = 200000; // 200kHz
long FREQ_MAX = 500000; // 500kHz
long ifreq = FREQ_MIN;
long freq = FREQ_MIN;


const unsigned long availableTimers[] = {oneMinute * 15, oneMinute * 30, oneMinute * 45, oneMinute * 60};
const byte maxTimers = 4;
int timerPosition = 0;
// по умолчанию 50% потенциометра
int currentPotenciometrPercent = 50;

 /********* используемые подпрограммы выносим сюда *********/

 /*** Обработчик кнопки энкодера ***/
//------Cl_Btn----------------------
enum {sbNONE = 0, sbClick, sbLong}; /*состояние не изменилось/клик/долгое нажатие*/
class Cl_Btn {
  protected:
    const byte pin;
    byte state;
    bool bounce = 0;
    bool btn = 1, oldBtn;
    unsigned long past;
    const uint32_t time = 500 ;
    bool flag = 0;
    uint32_t past_flag = 0 ;
  public:
    Cl_Btn(byte p): pin(p) {}
    /*инициализация-вставить в setup()*/
    void init() {
      pinMode(pin, INPUT_PULLUP);
    }
    /*работа-вставить в loop()*/
    void run() {
      state = sbNONE;
      bool newBtn = digitalRead(pin);
      if (!bounce && newBtn != btn) {
        bounce = 1;
        past = mill;
      }
      if (bounce && mill - past >= 10) {
        bounce = 0 ;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) {
          flag = 1;
          past_flag = mill;
        }
        if (!oldBtn && btn && flag && mill - past_flag < time ) {
          flag = 0;
          state = sbClick;
        }
      }
      if (flag && mill - past_flag >= time ) {
        flag = 0;
        state = sbLong;
      }
    }
    byte read() {
      return state;
    }
};

Cl_Btn Btn1(PIN_ENCODER_BUTTON); //Экземпляр обработчика для кнопки энкодера

/******* Простой энкодер *******/
#include <util/atomic.h>        // для атомарности чтения данных в прерываниях
#include <RotaryEncoder.h>
RotaryEncoder encoder(PIN_ENCODER1, PIN_ENCODER2);

volatile int newEncoderPos; // новая позиция энкодера
static int currentEncoderPos = 0; // текущая позиция энкодера
/*** Обработчик прерывания для энкодера ***/
 ISR(PCINT2_vect) {encoder.tick();}

// функция выбора времени работы
void setTimer() {
  // если энкодер крутим по часовой
  if (newEncoderPos - currentEncoderPos > 0) {
    if (timerPosition == maxTimers - 1) {
      timerPosition = 0;
    } else {
      timerPosition += 1;
    }
  } else if (newEncoderPos - currentEncoderPos < 0) {
    // если энкодер крутим против часовой
    if (timerPosition == 0) {
      timerPosition = maxTimers - 1;
    } else {
      timerPosition -= 1;
    }
  }
  memTimers = availableTimers[timerPosition];
}

void resetPotenciometer() {
  // Понижаем сопротивление до 0%:
  analogWrite(PIN_UD, 0); // выбираем понижение
  digitalWrite(PIN_CS, LOW); // выбираем потенциометр X9C
  for (int i=0; i<100; i++) { // т.к. потенциометр имеет 100 доступных позиций
    analogWrite(PIN_INC, 0);
    delayMicroseconds(1);
    analogWrite(PIN_INC, 255);
    delayMicroseconds(1);
  }
  digitalWrite(PIN_CS, HIGH); /* запоминаем значение и выходим из режима настройки */
}

// Уровень percent - от 0 до 100% от максимума.
void setResistance(int percent) { 
  resetPotenciometer();

  // Поднимаем сопротивление до нужного:
  analogWrite(PIN_UD, 255); // выбираем повышение
  digitalWrite(PIN_CS, LOW); // выбираем потенциометр X9C
  for (int i=0; i < percent; i++) {
    analogWrite(PIN_INC, 0);
    delayMicroseconds(1);
    analogWrite(PIN_INC, 255);
    delayMicroseconds(1);
  }

  digitalWrite(PIN_CS, HIGH); /* запоминаем значение и выходим из режима настройки */
}

void processPotenciometr() {
  // если энкодер крутим по часовой
  if (newEncoderPos - currentEncoderPos > 0) {
    if (currentPotenciometrPercent >= 100) {
      currentPotenciometrPercent = 100;
    } else {
      currentPotenciometrPercent += 1;
    }
  } else if (newEncoderPos - currentEncoderPos < 0) {
    // если энкодер крутим против часовой
    if (currentPotenciometrPercent <= 1) {
      currentPotenciometrPercent = 1;
    } else {
      currentPotenciometrPercent -= 1;
    }
  }

  setResistance(currentPotenciometrPercent);
}

/*** Обработчик энкодера через ШИМ ***/
void startEncoder() {
     attachInterrupt(1, Encoder2, RISING );
     analogWrite(PIN_ENCODER3, 0x80); //установим на пине частоту
                                //490 гц скважность 2
}
void Encoder2(void){ // процедура вызываемая прерыванием, пищим активным динамиком
     encoder.tick();
}

 /********* Таймер обратного отсчёта экспозиции **********/
unsigned long  setTimerLCD(unsigned long timlcd) {
  if (millis() - timMillis >=1000) {
    timlcd = timlcd - 1000;
    timMillis += 1000;
  }
  if (timlcd == 0) {
    timlcd = oldmemTimers;
    isWorkStarted = 0;
    lcd.setCursor(0, 3);
    lcd.print("     ЗАВЕРШЕНО!     ");
    digitalWrite(ON_OFF_CASCADE_PIN, LOW);
    start_Buzzer();
    delay(3000);
    stop_Buzzer();
    AD9833reset();
  }
  return timlcd;
}
/*******************ПИЩАЛКА ********************/
void start_Buzzer() {
    digitalWrite(PIN_ZUM, HIGH);
}

void stop_Buzzer() {
    digitalWrite(PIN_ZUM, LOW);
}

// ******************* Обработка AD9833 ***********************
// AD9833 documentation advises a 'Reset' on first applying power.
void AD9833reset() {
  WriteRegister(0x100);   // Write '1' to AD9833 Control register bit D8.
   delay(10);
 }

// Set the frequency and waveform registers in the AD9833.
void AD9833setFrequency(long frequency, int Waveform) {
  long FreqWord = (frequency * pow(2, 28)) / refFreq;
  int MSB = (int)((FreqWord & 0xFFFC000) >> 14);    //Only lower 14 bits are used for data
  int LSB = (int)(FreqWord & 0x3FFF);
  //Set control bits 15 ande 14 to 0 and 1, respectively, for frequency register 0
  LSB |= 0x4000;
  MSB |= 0x4000;
  WriteRegister(0x2100);
  WriteRegister(LSB);                  // Write lower 16 bits to AD9833 registers
  WriteRegister(MSB);                  // Write upper 16 bits to AD9833 registers.
  WriteRegister(0xC000);               // Phase register
  WriteRegister(Waveform);             // Exit & Reset to SINE, SQUARE or TRIANGLE
}

// *************************
// Display and AD9833 use different SPI MODES so it has to be set for the AD9833 here.
void WriteRegister(int dat) {
  SPI.setDataMode(SPI_MODE2);
  digitalWrite(PIN_FSYNC, LOW);           // Set FSYNC low before writing to AD9833 registers
  delayMicroseconds(10);              // Give AD9833 time to get ready to receive data.
  SPI.transfer(highByte(dat));        // Each AD9833 register is 32 bits wide and each 16
  SPI.transfer(lowByte(dat));         // bits has to be transferred as 2 x 8-bit bytes.
  digitalWrite(PIN_FSYNC, HIGH);          //Write done. Set FSYNC high
}

long readAnalogAndSetFreqInSetup() {
  int maxValue = 0;
  long freqWithMaxI = FREQ_MIN;
  long freqIncrease = 1000; // 1kHz
  int iterations = (FREQ_MAX-FREQ_MIN)/freqIncrease - 1; // (500000 - 200000) / 1000 - 1 = 199

  for (int j = 1; j <= iterations; j++) {
    // читаем значение аналогового входа
    int tempValue = analogRead(CORRECT_PIN);
    // если значение тока больше предыдущего, запоминаем это значение и текущую частоту
    if (tempValue > maxValue) {
      maxValue = tempValue;
      freqWithMaxI = freq;
    }
    // увеличиваем частоту для дальнейшего измерения тока
    freq = freq + freqIncrease;
    if (freq > FREQ_MAX) {
      freq = FREQ_MAX;
    }
    // подаём частоту на генератор
    AD9833setFrequency(freq, SINE);
    delay(20);
  }

  ifreq = freqWithMaxI;

  AD9833setFrequency(ifreq, SINE);
  prevReadAnalogTime = millis();
}

/**** Подстройка частоты каждые 1-10 секунд относительно аналогового сигнала ***/
void readAnalogAndSetFreqInLoop() {
  unsigned long curr = millis();

  // если прошло N секунд с момента последней проверки
  if (curr - prevReadAnalogTime > 1000 * 5) { //выбор времени изменения частоты.1-10 сек.
    long availableDiff = 5000; // 1kHz-10kHz разница частот
    long freqIncrease = 500; // 100Hz-1kHz шаг увеличения частоты при сканировании

    int iterations = (availableDiff * 2) / freqIncrease - 1; // (10000 * 2) / 1000 - 1 = 19

    long minimalFreq = ifreq - availableDiff;
    if (minimalFreq < FREQ_MIN) {
      minimalFreq = FREQ_MIN;
    }
    // подаём на генератор минимальную частоту из диапазона +-10кГц
    AD9833setFrequency(minimalFreq, SINE);
    delay(20);

    int maxValue = 0;
    long freqWithMaxI = minimalFreq;
    freq = minimalFreq;

    for (int j = 1; j <= iterations; j++) {
      // читаем значение аналогового входа
      int tempValue = analogRead(CORRECT_PIN);
      // если значение тока больше предыдущего, запоминаем это значение и текущую частоту
      if (tempValue > maxValue) {
        maxValue = tempValue;
        freqWithMaxI = freq;
      }
      // увеличиваем частоту для дальнейшего измерения тока
      freq = freq + freqIncrease;
      if (freq > FREQ_MAX) {
        freq = FREQ_MAX;
      }
      // подаём частоту на генератор
      AD9833setFrequency(freq, SINE);
      delay(10);
    }

    ifreq = freqWithMaxI;

    AD9833setFrequency(ifreq, SINE);
    prevReadAnalogTime = millis();
  }
}

//************************** SETUP *************************/
void setup() {
  // настройки потенциометра
  // сначала настраиваем потенциометр
  pinMode(PIN_CS, OUTPUT);
  pinMode(PIN_INC, OUTPUT);
  pinMode(PIN_UD, OUTPUT);
  digitalWrite(PIN_CS, HIGH);  // X9C в режиме низкого потребления
  analogWrite(PIN_INC, 255); 
  analogWrite(PIN_UD, 255); 
  
  delay(30);
  // сбрасываем потенциометр в 0%
  resetPotenciometer(); 
  // после сброса устанавливаем значение по умолчанию
  setResistance(currentPotenciometrPercent);

  // ждем секунду после настройки потенциометра
  delay(1000);
  
  Btn1.init();
  SPI.begin();
  Serial.begin(115200);

  pinMode(ON_OFF_CASCADE_PIN, OUTPUT);
  pinMode(PIN_ZUM, OUTPUT);
  pinMode(CORRECT_PIN, INPUT);

  digitalWrite(PIN_ZUM, LOW);
  digitalWrite(ON_OFF_CASCADE_PIN, HIGH);

  analogReference(INTERNAL);

  lcd.begin();
  lcd.backlight();
  delay(10);
  ina219.begin(0x40); // (44) i2c address 64=0x40 68=0х44 исправлять и в ina219.h одновременно
  ina219.configure(0, 2, 12, 12, 7); // 16S -8.51ms
  ina219.calibrate(0.100, 0.32, 16, 3.2);
  AD9833reset();                   // Ресет после включения питания
  delay(10);
  Serial.print("freq=");
  Serial.println(freq);
  // выставляем минимальную частоту для цикла определения максимального тока
  AD9833setFrequency(FREQ_MIN, SINE);
  delay(20);

  readAnalogAndSetFreqInSetup();

  Data_ina219=ina219.shuntCurrent() * 1000;
  myDisplay();
  delay(1000);
  PCICR |= (1 << PCIE2); // инициализируем порты для энкодера
  PCMSK2 |= (1 << PCINT20) | (1 << PCINT21);
  startEncoder();

  memTimers = availableTimers[0]; // выставляем 15 минут по умолчанию
}   

// *** ТЕЛО ПРОГРАММЫ ***
void loop() {
    mill = millis();
    Btn1.run();

    if (Btn1.read() == sbLong){
      oldmemTimers=memTimers;
      timMillis = millis();
      isWorkStarted = 1;
    }

    if (mill - prevUpdateDataIna > 1000 * 2) {
      Data_ina219=ina219.shuntCurrent() * 1000;
      prevUpdateDataIna = millis();
    }
    
    myDisplay();

    if (isWorkStarted == 1) {
      memTimers = setTimerLCD(memTimers);
    }

    ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
      newEncoderPos = encoder.getPosition();
    }

    // если значение экодера поменялось
    if (currentEncoderPos != newEncoderPos) {
      // если работа ещё не началась, то можем устанавливать время
      if (isWorkStarted == 0) {
        setTimer();
      } else if (isWorkStarted == 1) {
        // если работа ещё началась, то можем редактировать потенциометр
        processPotenciometr();
      }
      currentEncoderPos = newEncoderPos;
    }

    readAnalogAndSetFreqInLoop();
 }

display.ino

void myDisplay() {
  // 1 строка
  lcd.setCursor(0, 0);
   if (!isWorkStarted) {
    lcd.print("Время-");
    lcd.print(memTimers/60000);
    lcd.print(" мин. ");
  } else {
    lcd.print("Т-");
    if (memTimers > 60000) {
      // если больше минуты, то показываем минуты
      lcd.print(memTimers / 1000 / 60);
      lcd.print("мин.");
    } else {
      // если меньше минуты, то показываем секунды
      lcd.print(memTimers / 1000);
      lcd.print("сек.");
    }
    lcd.print(" U=");
    lcd.print(currentPotenciometrPercent);
    lcd.print("%  ");
  }

   // 2 строка
   lcd.setCursor(0, 1);
   lcd.print("F=");
   //lcd.setCursor(3, 1);                   //1 строка 7 позиция
   float freq_tic = ifreq;
   float kHz = freq_tic/1000;
   lcd.print(kHz, 0);
   lcd.print("kHz");

   // 2 строка
   lcd.setCursor(9, 1);
   lcd.print("I=");
   lcd.setCursor(11, 1);
   lcd.print(Data_ina219*2);
   lcd.print("ma");
 }

INA219.h

/******************************************************************************
* TI INA219 hi-side i2c current/power monitor Library
*
* http://www.ti.com/product/ina219
*
* 6 May 2012 by John De Cristofaro
*
*
* Tested at standard i2c 100kbps signaling rate.
*
* This library does not handle triggered conversion modes. It uses the INA219
* in continuous conversion mode. All reads are from continous conversions.
*
* A note about the gain (PGA) setting:
*	The gain of the ADC pre-amplifier is programmable in the INA219, and can
*	be set between 1/8x (default) and unity. This allows a shunt voltage 
*	range of +/-320mV to +/-40mV respectively. Something to keep in mind,
*	however, is that this change in gain DOES NOT affect the resolution
*	of the ADC, which is fixed at 1uV. What it does do is increase noise
*	immunity by exploiting the integrative nature of the delta-sigma ADC.
*	For the best possible reading, you should set the gain to the range
*	of voltages that you expect to see in your particular circuit. See
*	page 15 in the datasheet for more info about the PGA.
*
* Known bugs:
*     * may return unreliable values if not connected to a bus or at
*	bus currents below 10uA.
*
* Arduino 1.0 compatible as of 6/6/2012
*
* Dependencies:
*    * Arduino Wire library
*
* MIT license
******************************************************************************/

#ifndef ina219_h
#define ina219_h


#if ARDUINO >= 100
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#include <Wire.h>

#define INA219_DEBUG 1

// INA219 memory registers
#define CONFIG_R		0x00	// configuration register
#define V_SHUNT_R		0x01	// differential shunt voltage
#define V_BUS_R			0x02	// bus voltage (wrt to system/chip GND)
#define P_BUS_R			0x03	// system power draw (= V_BUS * I_SHUNT)
#define I_SHUNT_R		0x04	// shunt current
#define CAL_R			0x05	// calibration register

#define INA_RESET		0xFFFF	// send to CONFIG_R to reset unit

#define CONFIG_DEFAULT		0x399F

// config. register bit labels
#define RST	15
#define BRNG	13
#define PG1	12
#define PG0	11
#define BADC4	10
#define BADC3	9
#define BADC2	8
#define BADC1	7
#define SADC4	6
#define SADC3	5
#define SADC2	4
#define SADC1	3
#define MODE3	2
#define MODE2	1
#define MODE1	0

// default values
#define D_I2C_ADDRESS	0x40 // (64) - адрес по умочанию, перемычки на датчике разомкнуты
#define D_RANGE			1
#define D_GAIN			3
#define D_SHUNT_ADC		3
#define D_BUS_ADC		3
#define D_MODE			7
#define D_SHUNT			0.25
#define D_V_BUS_MAX		6
#define D_V_SHUNT_MAX		0.3
#define D_I_MAX_EXPECTED	1


class INA219
{
  public:
	INA219();
	
	// by default uses addr = 0x40 (both a-pins tied low)
	void begin(uint8_t addr = D_I2C_ADDRESS);

	void calibrate(float r_shunt = D_SHUNT, float v_shunt_max = D_V_SHUNT_MAX, float v_bus_max = D_V_BUS_MAX, float i_max_expected = D_I_MAX_EXPECTED);

	void configure(uint8_t range = D_RANGE, uint8_t gain = D_GAIN, uint8_t bus_adc = D_BUS_ADC, uint8_t shunt_adc = D_SHUNT_ADC, uint8_t mode = D_MODE);

	void reset();

	int16_t shuntVoltageRaw();
	int16_t busVoltageRaw();
	float shuntVoltage();
	float busVoltage();
	float shuntCurrent();
	float busPower();


  private:
	uint8_t i2c_address;
	float r_shunt, current_lsb, power_lsb;
	uint16_t config, cal, gain;

	int16_t read16(uint8_t addr);
	void write16(uint8_t addr, uint16_t data);

};

#endif

INA219.cpp

/******************************************************************************
* TI INA219 hi-side i2c current/power monitor Library
*
* http://www.ti.com/product/ina219
*
* 6 May 2012 by John De Cristofaro
*
*
* Tested at standard i2c 100kbps signaling rate.
*
* This library does not handle triggered conversion modes. It uses the INA219
* in continuous conversion mode. All reads are from continous conversions.
*
* A note about the gain (PGA) setting:
*	The gain of the ADC pre-amplifier is programmable in the INA219, and can
*	be set between 1/8x (default) and unity. This allows a shunt voltage 
*	range of +/-320mV to +/-40mV respectively. Something to keep in mind,
*	however, is that this change in gain DOES NOT affect the resolution
*	of the ADC, which is fixed at 1uV. What it does do is increase noise
*	immunity by exploiting the integrative nature of the delta-sigma ADC.
*	For the best possible reading, you should set the gain to the range
*	of voltages that you expect to see in your particular circuit. See
*	page 15 in the datasheet for more info about the PGA.
*
* Known bugs:
*     * may return unreliable values if not connected to a bus or at
*	bus currents below 10uA.
*
* Arduino 1.0 compatible as of 6/6/2012
*
* Dependencies:
*    * Arduino Wire library
*
* MIT license
******************************************************************************/

#include "INA219.h"
#include <util/delay.h>

INA219::INA219() {
}


void INA219::begin(uint8_t addr)
{
  Wire.begin();
  i2c_address = addr;
  gain = D_GAIN;
}


// calibration of equations and device
// shunt_val 		= value of shunt in Ohms
// v_shunt_max 		= maximum value of voltage across shunt
// v_bus_max 		= maximum voltage of bus
// i_max_expected 	= maximum current draw of bus + shunt
// default values are for a 0.25 Ohm shunt on a 5V bus with max current of 1A
void INA219::calibrate(float shunt_val, float v_shunt_max, float v_bus_max, float i_max_expected)
{
  uint16_t cal;
  float i_max_possible, min_lsb, max_lsb, swap;

  r_shunt = shunt_val;

  i_max_possible = v_shunt_max / r_shunt;
  min_lsb = i_max_expected / 32767;
  max_lsb = i_max_expected / 4096;

  current_lsb = (uint16_t)(min_lsb * 100000000) + 1;
  current_lsb /= 100000000;
  swap = (0.04096)/(current_lsb*r_shunt);
  cal = (uint16_t)swap;
  power_lsb = current_lsb * 20;

#if (INA219_DEBUG == 1)
  Serial.print("v_bus_max:	"); Serial.println(v_bus_max, 8);
  Serial.print("v_shunt_max:	"); Serial.println(v_shunt_max, 8);
  Serial.print("i_max_possible:	"); Serial.println(i_max_possible, 8);
  Serial.print("i_max_expected: "); Serial.println(i_max_expected, 8);
  Serial.print("min_lsb:	"); Serial.println(min_lsb, 12);
  Serial.print("max_lsb:	"); Serial.println(max_lsb, 12);
  Serial.print("current_lsb:	"); Serial.println(current_lsb, 12);
  Serial.print("power_lsb:	"); Serial.println(power_lsb, 8);
  Serial.println("  ");
  Serial.print("cal:		"); Serial.println(cal);
  Serial.print("r_shunt:	"); Serial.println(r_shunt);
#endif

  write16(CAL_R, cal);

}


// config values (range, gain, bus adc, shunt adc, mode) can be derived from pp26-27 in the datasheet
// defaults are:
// range = 1 (0-32V bus voltage range)
// gain = 3 (1/8 gain - 320mV range)
// bus adc = 3 (12-bit, single sample, 532uS conversion time)
// shunt adc = 3 (12-bit, single sample, 532uS conversion time)
// mode = 7 (continuous conversion)
void INA219::configure(uint8_t range, uint8_t gain, uint8_t bus_adc, uint8_t shunt_adc, uint8_t mode)
{
  config = 0;

  config |= (range << BRNG | gain << PG0 | bus_adc << BADC1 | shunt_adc << SADC1 | mode);

  write16(CONFIG_R, config);		
}

// resets the INA219
void INA219::reset()
{
  write16(CONFIG_R, INA_RESET);
  _delay_ms(5);
}

// returns the raw binary value of the shunt voltage
int16_t INA219::shuntVoltageRaw()
{
  return read16(V_SHUNT_R);
}

// returns the shunt voltage in volts.
float INA219::shuntVoltage()
{
  float temp;
  temp = read16(V_SHUNT_R);
  return (temp / 100000);
}

// returns raw bus voltage binary value
int16_t INA219::busVoltageRaw()
{
  return read16(V_BUS_R);
}

// returns the bus voltage in volts
float INA219::busVoltage()
{
  int16_t temp;
  temp = read16(V_BUS_R);
  temp >>= 3;
  return (temp * 0.004);
}

// returns the shunt current in amps
float INA219::shuntCurrent()
{
  return (read16(I_SHUNT_R) * current_lsb);
}

// returns the bus power in watts
float INA219::busPower()
{
  return (read16(P_BUS_R) * power_lsb);
}


/**********************************************************************
* 			INTERNAL I2C FUNCTIONS			      *
**********************************************************************/

// writes a 16-bit word (d) to register pointer (a)
// when selecting a register pointer to read from, (d) = 0
void INA219::write16(uint8_t a, uint16_t d) {
  uint8_t temp;
  temp = (uint8_t)d;
  d >>= 8;
  Wire.beginTransmission(i2c_address); // start transmission to device

  #if ARDUINO >= 100
    Wire.write(a); // sends register address to read from
    Wire.write((uint8_t)d);  // write data hibyte 
    Wire.write(temp); // write data lobyte;
  #else
    Wire.send(a); // sends register address to read from
    Wire.send((uint8_t)d);  // write data hibyte 
    Wire.send(temp); // write data lobyte;
  #endif

  Wire.endTransmission(); // end transmission
  delay(1);
}


int16_t INA219::read16(uint8_t a) {
  uint16_t ret;

  // move the pointer to reg. of interest, null argument
  write16(a, 0);
  
  Wire.requestFrom((int)i2c_address, 2);	// request 2 data bytes

  #if ARDUINO >= 100
    ret = Wire.read(); // rx hi byte
    ret <<= 8;
    ret |= Wire.read(); // rx lo byte
  #else
    ret = Wire.receive(); // rx hi byte
    ret <<= 8;
    ret |= Wire.receive(); // rx lo byte
  #endif

  Wire.endTransmission(); // end transmission

  return ret;
}

1 лайк


Совместима ли эта схема с программой или есть другой вариант схемы

Да. Эта схема нарисована одним нашим коллегой с моей схемы нарисованной на листке.

А можно ли, с помощью этой катушки, увеличить член на пару самнтиметров. Жене в отместку, ибо ображается.(

тут лучше аппарат, тот что для космонавтов, подойдёт, он жеж двойного действия

на Кавказе это алмасты

тут другой вопрос, в инете много предложений по такому генератору выполненному на промышленном уровне, может проще купить?
Знаю, что ведутся разработки генератора с модуляцией низкими частотами (по Хильде Кларк и автору темнопольного микроскопа), та тема, что Мишин с Гаряевым обсуждали, но Гаряев свою матрицу в качестве модулирующего сигнала предложил

неправильно ТТ включен, он должен работать на низкоомную нагрузку.
т.е. после диодного моста резистор на землю 10-100 Ом.
какой конкретно это считать надо
Скажем макс ток катушки 1А, тогда ТТ 1/100 отдаст 10мА,
и при 100 Ом нагрузки на выходе будет 1В
Сильно увеличивать резистор нельзя иначе ТТ перестанет работать как трансформатор тока.
L/R >= 10*1/2f - условие неискаженной передачи тока.
L- это индуктивность обмотки ТТ
R- резистор нагрузки
f -частота генератора

Раз R небольшое желательно чтобы и сопротивление обмотки было минимальным, т.к. оно вносит погрешность.

тогда и AREF надо скорректировать, не 4-4.5 вольта, а где-то 1.5

на резонансе, на ковиде, ток увеличивался с одного ампера до 1.4 - 1.5, укладываемся

Можно пожалуйста небольшой рисунок схемы?

выход моста нагрузить резистором 100 ом, остальные резисторы выкинуть

тт-1

Удалить R11 и изменить сопротивление R12 на 100 Ом?

правильно

надо тогда конденсатор убирать, иначе мост будет нагружен на емкость.

или R12 =100 и перенести на другую сторону от R11.

тогда емкость и R11 образуют фнч на входе ацп, параметры которого нужно посчитать.

Считать параметры? Для этого? Ну, где ток примерно такой, частота - около этого, но резонанс что-бы был вроде близкий к этому и …
Главное, что-бы “Решение средствами электростатики заключается в создании притока среды внутрь кластера, чтобы добиться его размагничивания, ослабления и размыкания вихревых связей. Это достигается за счет образования зоны пониженной плотности с помощью электростатического резонанса. Мы получаем втягивание среды в эту зону, аналогичное по механизму гравитационному притяжению”(с)

теперь бы ещё перевести на понятный язык, что он сказать хотел )))