DC DC Step UP 6 -100 вольт на Attiny85

Нужен был преобразователь на такие напряжения для малых токов (1-5ма), на алиэкспрессе не нашел, гугл у меня давно забанили, пришлось сделать самому. В тумбочке нашлись восьминоговые Attiny85 и Py32f003L18, с первыми всё проще, сделал на них, кто в силах одолеть а-ля STM32 может переработать код под второй чип, ну а если никто не в состоянии, придётся самому )))

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

И код, каюсь, заимствован у @dimax но в моей интерпретации:

#include <avr/io.h>
#include <avr/interrupt.h>

#define MAX_A 180
#define MAX_B 180 

volatile unsigned int adc_val[2];   // в [0] храним установленное значение в [1] с датчика Uвых.
unsigned int ad_temp0, ad_temp1,  ch;
volatile unsigned int temp;

int main(void) {

  DDRB = (1 << DDB1) | (1 << DDB0);   // pinMode OUTPUT
  ADMUX = (1 << ADLAR) | (1 << MUX0); // REF=Vcc, ADC1(pb2)=default input
  ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); //запускаем АЦП, разрешаем прерывания
  ADCSRB = 0;
  DIDR0  = (1 << ADC1D) | (1 << ADC2D); //запрет на цифровой вход
  TCCR0A = 0b10100011; // FAST PWM
  TCCR0B = 0b00000001;
  adc_val[0] = 0;
  adc_val[1] = 0;
  sei();
  OCR0A = 7;
  OCR0B = 7;

  while (1) {
    ad_temp0 = adc_val[0];
    ad_temp1 = adc_val[1];
    if (ad_temp1 < ad_temp0)  {
      OCR0A++; ch = OCR0A;
      if ( ch > MAX_A) OCR0A = MAX_A;
      OCR0B++; ch = OCR0B;
      if ( ch > MAX_B) OCR0B = MAX_B;
    }
    ad_temp0 = adc_val[0];
    ad_temp1 = adc_val[1];
    if (ad_temp1 > ad_temp0) {
      OCR0A--; ch = OCR0A;
      if (ch == 0) OCR0A = 1;
      OCR0B--; ch = OCR0B;
      if (ch == 0) OCR0B = 1;
    }
    for (temp = 0; temp < 270; temp++) {
      temp = temp + 1;
      temp = temp - 1;
    }
  }
}

ISR(ADC_vect) {
  unsigned int temp, temp1;
  unsigned char ch;
  ADCSRA &= ~(1 << ADEN);  //ADC остановлен
  temp1 = ADCL;
  temp = ADCH;
  temp = temp << 8;
  temp = temp | temp1;
  ADMUX & 1 ? (adc_val[1] = temp) : (adc_val[0] = temp);
  ADMUX ^= 1 << 1 | 1 << 0;
  ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); //запускаем АЦП, разрешаем прерывания
}

Плата может выглядеть как-то так:

1 лайк

Я так понимаю скважность уменьшается пока напряжение ниже порога?
А не будет ли ситуации когда АЦП ещё не прочитал или прочитал близко к порогу, а следующим импульсом напряжение уже выше нужного? Смущает делитель на 128. Не слишком медленно? Может лучше использовать компаратор или прерывание PCINT? А регулировать делителем в схеме.

ничё не знаю, схема рабочая, на 100 вольтах нагрузку 5ма держит, мне больше не надо, точнее мне надо всего 500 микроампер
Да, ШИМ 32 килогерца ежели что

На досуге смоделю код, интересно очень) Идея использовать МК в импульснике заманчива своей гибкостью, хоть и не надёжно, говорят.

мне нужна была регулировка, проект повторен два раза и не только мной, у меня трудится старый добрый 2SK3670 (ну не доверяю я китайцам) и UF4007, индуктивность намотана на колечке от материнской платы INTEL, там высокочастотные преобразователи (мегагерцы) так что пришлось мотать до заполнения проводом 0.35 (400 микрогенри), силовую можно сделать как угодно под себя

А что Qucs умеет моделировать AVR?

1 лайк

Стоило произнести фразу вслух, что не нашел DC-DC UP на нужное мне напряжение и вуаля

Сделан на чипе XL6007E1, такой чип есть в чип и дип, по 100 рублей, а вот даташит они приводят только на XL6007 а там на напряжение выходное только до 60 вольт
Из отзывов на аналогичные преобразователи:

Модуль интересный, очень маленького размера, выдает 309 вольт постоянного напряжения максимум, 
минусовой контакт у этого модуля общий, чтобы его запустить надо контакт "enable" замкнуть с плюсовым
 контактом входа Единственный минус, это очень маленькие дорожки для припайки проводов, 
собран на микросхеме XL6007E1

В любом случае мне нужна регулировка по I2C - а таких я не нашёл

До чего ж знакомо! Неужели у всех так? :slight_smile:

1 лайк

микрофона и камеры нет, значит отслеживается текст, если майор не врёт

Урывками попробовал перетащить логику кода на STM32F103CBT (проще отлаживать)
Как тут всё запущено, 66 строк, а результат ещё и не проглядывается:


void setup() {

  Serial.begin(115200);
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;               // разрешение тактирования порта A
  GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);  // PA0 - аналоговый вход
  GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1);  // PA1 - аналоговый вход
  GPIOA->CRL &= ~(GPIO_CRL_MODE2 | GPIO_CRL_CNF2);  // PA2 - аналоговый вход
  GPIOA->CRL &= ~(GPIO_CRL_MODE3 | GPIO_CRL_CNF3);  // PA3 - аналоговый вход

  //Включим тактирование АЦП. Он использует синхроимпульсы шины ABP2.
  RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;  // разрешение тактирование АЦП

  //Добавляем в блок инициализации.
  RCC->CFGR &= ~RCC_CFGR_ADCPRE_0;  // предделитель АЦП = 10 (/6)
  RCC->CFGR |= RCC_CFGR_ADCPRE_1;

  //Основные режимы АЦП устанавливаются в 2х регистрах управления ADC_CR1 и ADC_CR2.
  //Сейчас запретим в них все. Будем устанавливать только то, что нам нужно.
  ADC1->CR1 = 0;  // запрещаем все в управляющих регистрах
  ADC1->CR2 = 0;

  //Хотя, после сброса микроконтроллера их состояние уже будет таким – сброшены все биты.
  //Включим АЦП установкой бита ADON.
  ADC1->CR2 |= ADC_CR2_ADON;  // разрешить АЦП

  //Давайте установим время выборки для каждого канала примерно 2 мкс,
  //что соответствует 28,5 циклам. Добавляем.
  ADC1->SMPR2 |= ADC_SMPR2_SMP0_0 | ADC_SMPR2_SMP0_1;  // время выборки 28,5 циклов
  ADC1->SMPR2 &= ~ADC_SMPR2_SMP0_2;
  ADC1->SMPR2 |= ADC_SMPR2_SMP1_0 | ADC_SMPR2_SMP1_1;  // время выборки 28,5 циклов
  ADC1->SMPR2 &= ~ADC_SMPR2_SMP1_2;

  // выбор каналов
  ADC1->SQR1 = 0;                 // 1 регулярный канал
  ADC1->SQR3 = 0;                 // 1е преобразование - канал 0

  // Добавим калибровку в наш блок инициализации АЦП.
  // калибровка
  delayMicroseconds(10);          // задержка 10 мкс
  ADC1->CR2 |= ADC_CR2_CAL;       // запуск калибровки
  while ((ADC1->CR2 & ADC_CR2_CAL) != 0);  // ожидание окончания калибровки

  // Запуск преобразования АЦП может происходить от разных источников.
  // Источник запуска выбирается в поле EXTSEL [2:0] управляющего регистра  ADC1->CR2.
  // Эту тему подробно обсудим позже. А сейчас разрешим запуск от внешнего источника.
  // А в качестве источника выберем программный запуск.
  ADC1->CR2 |= ADC_CR2_EXTSEL;   // источник запуска - SWSTART
  ADC1->CR2 |= ADC_CR2_EXTTRIG;  // разрешение внешнего запуска для регулярных каналов
}

float result;        // переменная для результата

void loop() {
  // измерение сигнала
  // запуск АЦП
  ADC1->CR2 |= ADC_CR2_SWSTART;
  // ожидание завершения преобразования
  while (!(ADC1->SR & ADC_SR_EOC));

  result = (float)ADC1->DR * 3.300 / 4096.0;  // пересчет в напряжение

  Serial.print("ADC = ");
  Serial.println(result, 3);
  delay(300);
}

Ну хотя бы один потенциометр обрабатывается

19:26:32.787 -> ADC = 3.299
19:26:33.094 -> ADC = 2.649
19:26:33.373 -> ADC = 1.681
19:26:33.691 -> ADC = 1.177
19:26:34.006 -> ADC = 0.998
19:26:34.299 -> ADC = 0.796
19:26:34.613 -> ADC = 0.568

А? А что это?)
Погуглил. Нет. Я имел ввиду логику смоделировать, понять что когда и сколько.

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

Как же так, четыре VCP поднять не проблемма, а тут затык?

На тиньке, кстате, тоже програмный I2C можно было, вместо костыля на ЦАП.

Нарочно, что-ли повернул плату по всем осям? :))).

это художник так видит, имеет право, кому то нужно под лут?
Это под фрезеровку сделано

ну что там сказали эти - кандидаты в доктора?
PS а вот сделать средствами среды ардуино на STM32F103 видимо не получится, чтение аналогового пина занимает порядка 60 микросекунд
PPS только hard только CMSIS

Хардор! Только регистры) Кто бы сомневался. Ардуино ИДЕ вообще не годна для реалтайма. Не знаю как люди там выкручиваются. Напрямую в регистры писать только полдела. А вот отлаживать уже хрен там.

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

    for (temp = 0; temp < 270; temp++) {
      temp = temp + 1;
      temp = temp - 1;
    }

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

ну это ты погорячился, сама IDE очень даже ничего, там осталось чтение двух каналов прикрутить

#define MAX_A 180
#define MAX   200
#define DIVA	8

  void setup() {
	RCC->APB2ENR |= 1 << 2;  
	RCC->APB1ENR |= 1;       
	//PA0 - выход ШИМ канал 1 таймер 2
	GPIOA->CRL |= 0b1011;   
	GPIOA->CRL &= 0b1011;   
	TIM2->PSC = DIVA;       
	TIM2->ARR = MAX;        
	TIM2->CCR1 = 1;         
	TIM2->CCER |= 1;        
	TIM2->CCMR1 |= 3 << 5;  
	TIM2->CR1 |= 1;         
}

void loop() {

	for (int i = 10; i < 180; i++) {
		TIM2->CCR1 = i;
		delay(50);
	}
	for (int i = 180; i > 10; i--) {
	TIM2->CCR1 = i;
	delay(50);
	}
}

ЗЫ это A0 если из кода кто не видит

PS таймер 16-ти битный, если ограничится 10 битами, то максимальная частота будет 35 килогерц, то-есть можно сделать что-то и помощнее

Это основная идея данной темы.
Надо получить напряжение, возьмем вот такую схему, почему такие значения - “кто жеж знает, но работает”. Возьмем вот такой код, как он работает, почему именно такая частота ШИМ и такие пределы регулировки “кто жеж знает, но работает”.

2 лайка