TorAllex ©:И вот что ещё. Оперируем целыми полупериодами, т.е. при напряжении сети 220 В имеем шаг регулировки 2,2 В. Не грубовато получится?
Да, грубо. У меня мощность в процентах как наследие, нужно сделать шаг меньше - 0.5% скажем. Впрочем совсем уж жесткий предзахлеб я не использую.
Алсо, скетч ниже.
#include <DallasTemperature.h>
#include <avr/delay.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <math.h>
LiquidCrystal_I2C lcd(0x3f,16,2);
OneWire oneWire(7);
DallasTemperature sensors(&oneWire);
DeviceAddress columnSensor = {0x28, 0xFF, 0x21, 0x32, 0x8C, 0x16, 0x03, 0x4F};
DeviceAddress headSensor = {0x28, 0xFF, 0x4D, 0x22, 0x93, 0x16, 0x04, 0xD1};
#define ABTN 8
#define BBTN 9
#define CBTN 10
#define DBTN 11
#define SIGNAL_PIN 6
void setup()
{
lcd.init();
lcd.backlight();
//Serial.begin(9600);
lcd.setCursor(0, 1);
lcd.print("Setup");
pinMode(13, OUTPUT);
pinMode(SIGNAL_PIN, OUTPUT);
pinMode(ABTN, INPUT_PULLUP);
pinMode(BBTN, INPUT_PULLUP);
pinMode(CBTN, INPUT_PULLUP);
pinMode(DBTN, INPUT_PULLUP);
digitalWrite(SIGNAL_PIN, HIGH);
while (pollButtons() < 1) {}
digitalWrite(SIGNAL_PIN, LOW);
ADMUX |= (1<<REFS0);
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Use prescale factor 16 -> ADC clock is 500kHz
ADCSRA |= (1 << ADATE); // Enable auto-triggering
ADCSRA |= (1<<ADIE); //Enable ADC conversion complete interrupt
ADCSRA |= (1<<ADEN); //Enable the ADC
ADCSRA |= (1<<ADSC); //Start first conversion in Free-running mode
//ADMUX = ADMUX | B00000001;
ADMUX |= (1<<MUX0);
pinMode(13, OUTPUT);
EICRA |= (1<<ISC00)|(1<<ISC01);
EIMSK |= (1 << INT0);
//OCR0A = 100;
//TIMSK0 |= (1<<OCIE0A);
sensors.begin();
sensors.setWaitForConversion(false);
sensors.setResolution(columnSensor, 12);
sensors.setResolution(headSensor, 12);
sensors.requestTemperatures();
delay(1000);
sei();
}
int8_t pollButtons()
{
uint8_t pins[] = {ABTN, BBTN, CBTN, DBTN};
static unsigned long ms = 0;
if ((millis() - ms) > 100)
{
for (uint8_t i = 0; i < sizeof(pins); i++)
{
if (digitalRead(pins[i]) == LOW)
{
ms = millis();
return pins[i];
}
}
}
return -1;
}
#define V_RATIO 0.783
volatile uint32_t rmsS = 0;
volatile uint16_t rmsN = 0;
ISR(ADC_vect)
{
if (rmsN < 10000)
{
int16_t sample = ADCW - 512;
rmsS += (uint32_t)sample * (uint32_t)sample;
rmsN++;
}
}
volatile uint8_t pwmCalc = 50;
ISR(INT0_vect)
{
static uint8_t mod = 0;
mod += pwmCalc;
if (mod >= 100)
{
mod -= 100;
digitalWrite(13, HIGH);
}
else
{
digitalWrite(13, LOW);
}
}
void loop()
{
bool refreshLcd = true;
static uint16_t comp = 0;
static uint8_t pwmSet = 0;
static uint32_t dsms = 0;
switch (pollButtons())
{
case ABTN:
{
if (comp > 0) comp -= 10;
break;
}
case BBTN:
{
if (comp < 1000) comp += 10;
break;
}
case CBTN:
{
if (pwmSet > 0) pwmSet--;
break;
}
case DBTN:
{
if (pwmSet < 100) pwmSet++;
break;
}
default:
refreshLcd = false;
break;
}
static double voltage;
if (rmsN == 10000)
{
voltage = V_RATIO * sqrt(rmsS / rmsN);
rmsS = 0;
rmsN = 0;
double calc = (230.0 / voltage) * pwmSet;
if (calc > 100)
calc = 100;
pwmCalc = (uint8_t)round(calc);
}
static double headT, columnT;
if ((millis() - dsms) > 1000)
{
headT = sensors.getTempC(headSensor);
columnT = sensors.getTempC(columnSensor);
sensors.requestTemperatures();
dsms = millis();
refreshLcd = true;
if ( (comp > 0) && (abs(columnT - headT) > (double)(comp / 100.0)) )
{
digitalWrite(SIGNAL_PIN, HIGH);
}
else
{
digitalWrite(SIGNAL_PIN, LOW);
}
}
if (refreshLcd)
{
lcd.setCursor(0, 1);
lcd.print(pwmSet);
lcd.print(" ");
lcd.print(pwmCalc);
lcd.print(" ");
lcd.print(voltage, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(headT);
lcd.print(" ");
lcd.print(columnT);
lcd.print(" ");
lcd.print(comp / 100.0, 1);
lcd.print(" ");
}
}
Два полиэтиленовых бидона по 41 л.
Скаммерческий дистиллятор с укреплением.
РК 28/1700
Регулятор - термометр на ардуино с функцией пищания.