Собрал стабилизатор из латора по этой схеме настроить как положено так и не удалось,
так как корпус и вся обвязка была уже готова решил сделать новые мозги на меге8.
Программа должна работать так:
При первом включении проверяем корректность данных еепром если там мусор то пикаем, если все нормально крутим программу.
Для работы схемы нужно запомнить минимальное и максимальное напряжение, это делается через кнопки одна из которых заведена через инт0
Программа считывает данные с АЦП и включает один из десяти оптопар. Так же на радиатор посажу дс18б20 и по температуре через ШИМ будет управлять вентилятором (эта часть кода не проверена).
Мега тактируется внутренним генератором на 1МГц, обвязка АЦП стандарт: Avcc через 0,1мкф на минус и через 10мкГн на плюс, ADC0 через 0,1 на минус, резистивный делитель 100к/30к (Uin 10V Uout 2.31V).
Основная часть программы хорошо работает если входное напряжение изменяется почти во всем диапазоне ( от 1 до 10В)
При изменении сетевого напряжения с 220в до 175в на измерительной обмотке трансформатора напряжение меняется от 6,2в до 8в
на этом диапазоне оптопары переключаются как попало хотя должны работать нормально. Вот код подскажите что не так.
' Стабилизатор напряжения 11,02,3016
$regfile = "m8def.dat"
$crystal = 1000000
$eeprom
Dim W As Word ' Значение АЦП
Dim Q As Byte ' Количество выборок
Dim S As Word ' Сумма выборок
Dim A As Single ' Среднее значение АЦП
Dim Aw As Word
Dim Z As Bit ' Флаг считаной кнопки
Dim P As Single ' Значение ШИМ
Dim Pw As Word
Dim Y As Byte
Dim Errr As Bit ' Флаг ошибки данных EEPROM
Dim Mi As Word ' Переменная минимального напряжения в оперативной памяти
Dim Midata As Eram Word ' Переменная минемального напряжения в eeprom
Dim Ma As Word ' Переменная максимального напряжения в оперативной памяти
Dim Madata As Eram Word ' Переменная максимального напряжения в eeprom
Dim Razdata As Eram Word ' Переменная разности в eeprom
Dim Disdata As Eram Single ' Переменная велечины одной дискреты в eeprom
Dim Raz As Word
Dim Dis As Single
Dim T As Word ' максимально допустимое напряжениеDim O As Byte
Dim B As Byte
Dim C As Byte
Dim D As Byte
Dim E As ByteConfig Portb.7 = Input ' максимальное напряжение
Config Portd.2 = Input ' минимальное напряжениеConfig Portd.5 = Output ' LED
Config Portd.3 = Output ' bsn304
Config Portd.0 = Output ' ALARMConfig Portc.5 = Output ' 1
Config Portc.4 = Output ' 2
Config Portc.3 = Output ' 3
Config Portc.2 = Output ' 4
Config Portc.1 = Output ' 5
Config Portb.5 = Output ' 6
Config Portb.4 = Output ' 7
Config Portb.3 = Output ' 8
Config Portb.2 = Output ' 9
Config Portb.0 = Output ' 10Config Int0 = Falling ' Прерывание по нисходящему фронту
On Int0 Button
Enable Interrupts ' Разрешаем прерывания
Enable Int0
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Prescale = 8 'F_PWM=244HzConfig 1wire = Portd.1
Config Adc = Free , Prescaler = Auto , Reference = Internal
Config Watchdog = 2048 ' Сброс через 2секундыStart Adc ' Запускаем АЦП
Start Watchdog ' Запускаем сторожевого пса
A = 0
P = 0
Errr = 0
T = 0
Pwm1a = 0
Portd.5 = 0
Portd.3 = 0
Portd.0 = 0
'-----------------------------Начало основного цикла----------------------------
Do
Reset Watchdog ' Сбрасываем сторожевого пса
1wreset ' Проверяем наличее датчика температуры
If Err = 1 Then
'Errr = 1
End If
1wwrite &HCC ' Запрос на считывание данных из DS18B20
1wwrite &H44
Hom:
Mi = Midata ' Считываем значение Min из EEPROM
Ma = Madata ' Считываем значение Max из EEPROM
Raz = Razdata ' Считываем значение разности из EEPROM
Dis = Disdata ' Считываем значение одной дискреты из EEPROM
T = Dis * 4 ' Напряжение больше максимального на 4 дискреты
T = T + Ma
If Mi < 1 Or Ma > 1023 Or Mi > Ma Then ' Если минемальное или максимальное значение EEPROM неверные
Portd.0 = 1 ' ALARM
Waitms 200
Portd.0 = 0
Waitms 100Goto Hom ' Считать ошибкой данных EEPROM
End If
S = 0
'----------------------------Среднее арифметическое----------------------------
For Q = 0 To 10 '
W = Getadc(0)
S = S + W ' '
Waitms 100
Next Q '
A = S / 10 ' '
Aw = Round(a)
'------------- Номер оптопары -----------------------
If Aw >= Mi And Aw <= Ma Then
Pw = Aw - Mi
P = Pw / Dis
Y = Round(p)
End IfIf Aw < Mi Then
Y = 0
End IfIf Aw > Ma And Aw < T Then
Y = 9
End IfIf Aw > T Then
Y = 10
Errr = 1
End If
Reset Watchdog ' Сбрасываем сторожевого пса
'-------------------------------Включаем нужную оптопару----------------------------------
If Y = 0 Then
Set Portc.5
Else
Reset Portc.5
End IfIf Y = 1 Then
Set Portc.4
Else
Reset Portc.4
End IfIf Y = 2 Then
Set Portc.3
Else
Reset Portc.3
End IfIf Y = 3 Then
Set Portc.2
Else
Reset Portc.2
End IfIf Y = 4 Then
Set Portc.1
Else
Reset Portc.1
End IfIf Y = 5 Then
Set Portb.5
Else
Reset Portb.5
End IfIf Y = 6 Then
Set Portb.4
Else
Reset Portb.4
End IfIf Y = 7 Then
Set Portb.3
Else
Reset Portb.3
End IfIf Y = 8 Then
Set Portb.2
Else
Reset Portb.2
End IfIf Y = 9 Then
Set Portb.0
Else
Reset Portb.0
End If
Reset Watchdog ' Сбрасываем сторожевого пса
'--------------Считываем температуру и если надо включем винтелятор--------------
1wreset
1wwrite &HCC
1wwrite &HBE
O = 1wread()
B = 1wread()
If O > 248 Then
O = &HFF - O
B = &HFF - B
E = 2
Else
E = 1
End If
C = O / 16
D = B * 16
C = C + D
If E = 2 Then C = C + 1
If E = 1 And C = 0 Then E = 0
'If E = 2 Then Errr = 1If C > 40 And C < 44 Then
Pwm1a = 255
Waitms 500
Pwm1a = 185
End If
If C > 45 And C < 49 Then Pwm1a = 190
If C > 50 And C < 54 Then Pwm1a = 195
If C > 55 And C < 59 Then Pwm1a = 205
If C > 60 And C < 64 Then Pwm1a = 215
If C > 65 And C < 69 Then Pwm1a = 225
If C > 70 And C < 74 Then Pwm1a = 235
If C > 75 And C < 79 Then Pwm1a = 245
If C > 80 And C <= 89 Then Pwm1a = 255
If C > 89 Then Errr = 1If Y >= 0 And Y < 10 And Errr = 0 Then
Portd.3 = 1
Else
Portd.3 = 0 ' Подаем питание на оптопары
Portd.0 = 1
End IfLoop
End
'---------------Подпрограмма прирывания по кнопки-------------------------------
Button: ' Обработка прерывания по кнопки
Stop Watchdog ' Останавливаем сторожевого пса
Portd.0 = 0
Portd.3 = 0 ' Выключаем оптопары
Portd.5 = 1 ' зажигаем светодиод
Z = 0 ' Сброс флага удачного считывания
S = 0
For Q = 0 To 10
W = Getadc(0) '
S = S + W ' '
Waitms 100
Next Q '
A = S / 10
Mi = Round(a)
Portd.0 = 1 ' ALARM
Waitms 200
Portd.0 = 0
' считываем значение АЦП и запоминаем его как минимальное
Do ' Сохраняем значение минимального напряжения ' Нажата кнопка минимальное напряжение
If Pinb.7 = 0 Then ' Ждем нажатия кнопки максимального напряжения
Z = 1 ' Нажатие считано
S = 0
For Q = 0 To 10
W = Getadc(0) '
S = S + W ' '
Waitms 100
Next Q 'A = S / 10
Ma = Round(a) ' считываем значение АЦП и запоминаем его как максимальное
End If
Loop Until Z <> 0 ' Если дребезг помешал вычислению нажатой кнопки, повторяемRaz = Ma - Mi ' Вычисляем разность между максимальной и минемальным напряжении
Dis = Raz / 9 ' Вычисляем значение одной дискреты
Midata = Mi ' Сохраняем в EEPROM значение минемального напряжения
Madata = Ma ' Сохраняем в EEPROM значение максимального напряжения
Razdata = Raz ' Сохраняем в EEPROM значение разности между напряжениями
Disdata = Dis ' Сохраняем в EEPROM значение одной дискреты
Portd.0 = 1 ' ALARM
Waitms 200
Portd.0 = 0
Waitms 500
Portd.0 = 1 ' ALARM
Waitms 200
Portd.0 = 0
Waitms 500
Portd.5 = 0 ' Тушим светодиод
Start Watchdog ' Запускаем сторожевого пса
Gifr = 64 ' Сброс флага прерывания
Return