Да, безусловно, как посадить катоды на землю прекрасно понимаю, а будет ли так работать, имею ввиду без програмной смены полярности на выходах мк (порты 0-7) ?
Скетч править -- это само собой. Сейчас глянул, всего придется вносить изменения в три строки. Одна строка (номер 207) в обработчике прерывания COMPA, и две (261-262) в COMPB. Смысл простой -- там, где для общего анода бит выставляется, для общего катода он должен сбрасываться и наоборот.
Dm77 пишет:
Ребят. схема протестирована.
А получилось что-то с экранированием?
Не стал городить поддоны. В принципе кроме как дрожания символов паяние не страдает. А это главное. Думаю просто вынести плату в отдельный маленький корпус (благо не греется ничего) и питаль от ноутбучного БП.
В принципе, если предполагаются тяжелые помеховые условия эксплуатации, как в случае с "фонящим" блоком питания, то можно режим индикации заданной температуры, вместо измеренной, выбрать в качестве основного. Даже если нагреватель будет отрабатывать не совсем точно, то за счет интерности жала температура на кончике будет в значительной степени усредняться близ заданного значения.
Я поставил 0,125Вт, работает. Цвет не поменяли, рукой подлезть потрогать не подлезть. Эти сопротивления работают в короткий промежуток времени , пока не включится симистор, а это происходит в начале полупериода. Так что все гут!
Порядком достало, что плата на проводах по столу ездит, решил прикрутить на общее основнание и закрепить кабель. Основанием послужила какая-то старая и давно распаянная на запчасти плата неизвестно от чего. Вот, что получилось:
Сверху от паялки можно наблюдать плату преобразователя (DC-DC) 12 вольт на 24 вольта. Так как питание от настольного компа у меня основное, а после замеров скорости нагрева выяснилось, что разогрев с 12 вольт получается долгий, то решил дополнить устройство бустером:
Данная повышайка собрана на контроллере UC3843 по схеме близкой к референсной. Дроссель намотан на кольце со старой материнской платы. Материал №52, цвет салатовый с синим, размеры 15,5 х 8,5 х 6 мм. Использовался сложенный вдвое провод диаметром 0,5мм, который наматывался без предварительного расчета из соображений "сколько влезет". Измеренная индуктивность в итоге составила 22мкГн, что вполне устроило. Изначально были представления, что кольцо должно быть существенно больше размерами, т.к. планировалось снимать с него более 50 Ватт мощности, но эксперимент показал, что и это двольно компактное кольцо вполне работоспособно при нагреве до 50-60 градусов во время работы.
Так как микросхема у меня была в корпусе под поверхностный монтаж, то основная часть деталей также размещена на стороне дорожек:
Мосфет с допустимым током до 80 ампер выдран с той же материнки. Большинство деталей надерганы с плат из ящика с радиохламом. В общем, получилось довольно бюджетно и приемлемо по параметрам. Если у кого-то возникнет желание повторить, могу выложить схему и чертеж платы.
Некоторые элементы я забрал в рамку из пунктира, чтобы пометить, что присутствие этих деталей желательно, но если по каким-то причинам нет возможности их раздобыть, то можно не ставить. Единственное уточнение -- резистор R4 не просто не устанавливать, а заменить перемычкой.
Полуваттные резисторы R6-R9 включены в параллель, чтобы набрать общее сопротивление 0.025 ома. Единичных сопротивлений столь малой величины среди запасов и в продаже отыскать не удалось, т.ч. пришлось параллелить то, что оказалось доступно. В принципе, там можно поставить одно сопротивление 0.025 ома мощностью 1-2 ватта. Столь экзотический резистор в схеме присутствует для ограничения максимального тока через ключ. Если поставить резистор с большим номиналом, то преобразователь будет давать просадку напряжения при пиковых нагрузках, если номинал выбрать ниже, то увеличится нагрузка на источник.
Диод D2 -- это Шоттки с рабочим током не ниже 3 ампер (например, B340, SS34, B34, SK34 и т.п.). На самом деле пиковые нагрузки на этот диод в данной схеме существенно выше, но у большинства производителей данные приборы держат в пике по 80-120 ампер, т.ч. их использование вполне тут оправдано. В принципе, величина тока в большинстве случаев ограничивается тепловыделением кристала и если обеспечить должный теплоотвод, то рабочий ток можно смело задирать.
Мосфет лучше выбирать с минимальным значением сопротивления канала в открытом состоянии (Rds) и на напряжение не ниже 30 вольт. Хорошо себя показали мощные мосфеты с материнских плат.
Вообще, данную повышайку можно использовать не только применительно к паялке, но и для любых других надобностей, где возникает потребность повысить напряжение. На вход можно подавать любое напряжение из диапазона 9в..30в, а с выхода получать не ниже, чем входное. По похожим схемам делают бустеры вольт до четырехсот и выше. Разумеется, детали силовой части должны быть расчитаны на подобные напряжения.
Выходное напряжение определяется величинами R10, R11+R12 в резиситвном делителе. Можно их рассчитать по формуле V(out) = 2.5 * (1 + R10/(R11 + R12)), но я как-то привык пользоваться онлайн-калькулятором. Поле "Input Voltage" оставляем пустым, в поле "Output voltage" заносим константу 2.5, а R1 и R2 -- это R10 и R11+R12 с вышеприведенной схемы. "Играя" значениями в полях R1 и R2 можно подобрать номиналы делителя на желаемое выходное напряжение.
Если вникать в тонкости схемы нет желания, а просто хочется повторить устройство, то вот вариант схемы и платы в формате протеуса. Размеры платы специально сделаны попросторнее, т.к. пустые участки меди служат радиатором, отводя тепло от греющихся элементов -- диода и мосфета.
Здравствуйте. Собрал себе паяльную станцию по проекту a5021 (за что ему отдельное большое спасибо). Споткнулся на калибровке. Не могу понять, как (или где) увидеть значения getOversampled(). Может я задаю глупый вопрос, но до этого проекта с ардуиной не имел дела. А после прочтения форума появилось желание для начала просто повторить. Поэтому, если не трудно разъясните более подробно. И после того, как я выясню значения getOversampled(), нужно заново заливать скетч в ардуину?
Я уже где-то выше писал, что, по идее, процедура калибровки должна быть встроенная, но пока у меня так и не хватило сил и времени, чтобы написать ее в полном объеме. Поэтому на данный момент калибровка страдает изрядной горбатостью, когда нужно сначала выяснить эти самые значения getOversampled(), затем внести полученные значения в исходники и перезалить скетч.
О том, как проще выяснить, что там getOversampled() возвращает: мне в голову не пришло ничего лучше, как сделать довольно грубый хак, чтобы скетч показывал эти значения на основном индикаторе. Это не самое лучшее решение, но зато быстрое. В общем, если раскомментировать определение CALIBRATION_BUILD в тексте скетча, что я прикладываю ниже, то после его сборки и заливки паялка потеряет почти весь свой функционал, перестанет включать нагреватель вообще, но зато будет показывать на дисплее три последние цифры значения, возвращаемого функцией getOversampled(). Старшая цифра без сильного нагрева всегда 1, а если греть дальше, то можно отследить смену старшего разряда по переходу значений на индикаторе через ноль.
Тут подумалось, что для калибровки, возможно, удобно будет воспользоваться медицинским термометром, как прибором достаточно точным в рамках некоторого диапазона. Процедура может быть следующей: заливаем в паялку скетч с раскомментированным определением CALIBRATION_BUILD. Наливаем в некую посудину теплой воды, по температуре близкой к температуре человеческого тела. Посудину лучше чем-нибудь укутать, чтобы быстро не остывала. Раскручиваем паяльник, чтобы нагреватель торчал наружу и помещаем его (нагреватель) в воду. В эту же воду помещаем медицинский термометр. Включаем паялку. Ждем некоторое время, пока все прогреется и записываем значения с термометра и дисплея паялки на бумажку. Выливаем воду и убираем медицинский термометр. Теперь берем другой термометр, с помощью которого можно измерять температуту горячей воды, наливаем в посудину кипяток из чайника и схоожим образом фиксируем новые значения. Переносим числа с бумажки в текст скетча, выносим CALIBRATION_BUILD в комментарии и перезаливаем скетч. Вытираем нагреватель, скручиваем паяльник. Все, паялка откалибрована и готова к работе.
Ну и сам скетч в новой версии. Никаких новых фич, кроме возможности сборки калибровочного билда в нем нет, т.ч. тем, кто уже пользуется данной паялкой смысла его заливать никакого нет.
/*
**
** ARDUINO Soldering Station TH v1.21 (c) a5021
** march - september 2015
**
** http://arduino.ru/forum/proekty/payalnaya-stantsiya-iz-arduino
**
** HISTORY
** =======
** september 2015 -- version 1.21:
* - added CALIBRATION_BUILD conditional compilation macro;
** august 2015 -- version 1.2:
** - improved temperature keeping stability;
** - ADC procedure rewritten;
** - several code improvements;
** july 2015 -- version 1.02:
** - fixed some stupid errors in preHeat() pprocedure;
** july 2015 -- version 1.01:
** - added preheat procedure;
** may 2015 -- version 1.00:
** - first public release
*/
#include <avr/sleep.h>
//#define CALIBRATION_BUILD 1
// use PREHEAT_ENABLE in case the PSU is not powerful enough
// this force PWM-mode preheating when soldering iron is cold
#define PREHEAT_ENABLE 1
// ohmic value of the upper resistor in the voltage divider
#define R1 220.0
// external voltage reference (TL431)
#define V_REF 2.495
// calibrated atmega's internal voltage reference
#define REFERENCE_1V1 1.087
/*
** soldering iron's thermal probe calibration data definitions
**/
#define CALIBRATION_TEMP_LOW ((unsigned int) 2950)
#define CALIBRATION_TEMP_HIGH ((unsigned int) 18300)
#define ADC_CALIBRATION_DATA_LOW ((unsigned int) 1658)
#define ADC_CALIBRATION_DATA_HIGH ((unsigned int) 2373)
/*
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
*/
// low temperature degree (multiplied by 100)
#define LOW_TEMP_DEGREE ((unsigned int)18500)
// high temperature degree (multiplied by 100)
#define HIGH_TEMP_DEGREE ((unsigned int)45800)
#define HIGH_TEMP_MARGIN ((unsigned long int)(HIGH_TEMP_DEGREE - CALIBRATION_TEMP_LOW) * \
(ADC_CALIBRATION_DATA_HIGH - ADC_CALIBRATION_DATA_LOW) \
/ (CALIBRATION_TEMP_HIGH - CALIBRATION_TEMP_LOW) \
+ ADC_CALIBRATION_DATA_LOW)
#define LOW_TEMP_MARGIN ((unsigned long int)(LOW_TEMP_DEGREE - CALIBRATION_TEMP_LOW) * \
(ADC_CALIBRATION_DATA_HIGH - ADC_CALIBRATION_DATA_LOW) \
/ (CALIBRATION_TEMP_HIGH - CALIBRATION_TEMP_LOW) \
+ ADC_CALIBRATION_DATA_LOW)
// min timeout in seconds
#define MIN_TIMEOUT_SEC 15
// max timeout in seconds
#define MAX_TIMEOUT_SEC (60 * 60)
// low power mode duration in seconds
#define LOW_POWER_MODE_DURATION (15 * 60)
// num of beeps before go standby
#define TICK_TOCK_COUNT 10
// time before the display to be dimmed
#define TIME_BEFORE_DIM 10
#ifndef CALIBRATION_BUILD
// heater control macros
#define TURN_HEATER_ON sbi(PORTB, PORTB1)
#else
#define TURN_HEATER_ON cbi(PORTB, PORTB1)
#endif
#define TURN_HEATER_OFF cbi(PORTB, PORTB1)
// LED signaling
#define TURN_LED_ON sbi(PORTB, PORTB5)
#define TURN_LED_OFF cbi(PORTB, PORTB5)
// display brightness constants
#define MIN_BRIGHTNESS 0xEF
#define DEFAULT_BRIGHTNESS 0xB0
// where segment's cathodes are connected to
#define SEG_A (1 << PORTD5)
#define SEG_B (1 << PORTD7)
#define SEG_C (1 << PORTD0)
#define SEG_D (1 << PORTD3)
#define SEG_E (1 << PORTD4)
#define SEG_F (1 << PORTD6)
#define SEG_G (1 << PORTD1)
#define SEG_DP (1 << PORTD2)
// compose digits using separate segments
#define SIGN_8 (0xFF - SEG_DP)
#define SIGN_0 (SIGN_8 - SEG_G)
#define SIGN_1 (SEG_B + SEG_C)
#define SIGN_2 (SIGN_8 - SEG_C - SEG_F)
#define SIGN_3 (SIGN_8 - SEG_E - SEG_F)
#define SIGN_4 (SIGN_1 + SEG_F + SEG_G)
#define SIGN_6 (SIGN_8 - SEG_B)
#define SIGN_5 (SIGN_6 - SEG_E)
#define SIGN_7 (SIGN_1 + SEG_A)
#define SIGN_9 (SIGN_8 - SEG_E)
#define SIGN_BLANK 0
// compose some letters
#define SIGN_E (SIGN_6 - SEG_C)
#define SIGN_F (SIGN_E - SEG_D)
#define SIGN_r (SEG_G + SEG_E)
#define SIGN_n (SIGN_r + SEG_E)
// bit manipulation macros
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// number-to-7seg code translation table
const unsigned char codeTable[] = {~SIGN_0, ~SIGN_1, ~SIGN_2,
~SIGN_3, ~SIGN_4, ~SIGN_5,
~SIGN_6, ~SIGN_7, ~SIGN_8,
~SIGN_9};
// signs to be displayed
volatile unsigned char displayBuffer[] = {~SIGN_0, ~SIGN_F, ~SIGN_F},
globalEvent = 0, // bitset for event handling
displayUpdateReq = 0,
readPotReq = 0,
currentDigit = 0; // active digit at display
volatile unsigned int softTimer = 0, // software timer downcounter
dimCounter = TIME_BEFORE_DIM, // dim downcounter
toCounter1, // time before low power mode
toCounter2, // low power mode downcounter
toneDuration = 0; // sound duration counter
/*
** application's event flags
*/
// keypress flag
#define EVENT_BUTTON_PRESSED (1<<0)
// button pressed for a long time
#define EVENT_BUTTON_LONG (1<<1)
// request tone generation
#define EVENT_BEEPER_REQ (1<<2)
// warming up or cooling down request
#define EVENT_TEMP_CHANGE_REQ (1<<3)
// audio alarm request
#define EVENT_TICK_TOCK_REQ (1<<4)
// attention request
#define EVENT_ATTN_REQ (1<<5)
// low power mode flag
#define EVENT_LOW_POWER_MODE (1<<6)
// go standby flag
#define EVENT_STANDBY_MODE (1<<7)
/*
** flag manipulation macros
*/
#define SET_EVENT(EVENT) cli(); globalEvent |= (EVENT); sei()
#define CLEAR_EVENT(EVENT) cli(); globalEvent &= ~(EVENT); sei()
#define CHECK_EVENT(EVENT) (globalEvent & (EVENT))
void resetTimeout(unsigned int temperature) {
unsigned int m;
// calculate new timeout value based on current temperature
OCR0B = DEFAULT_BRIGHTNESS; // restore display brightness
if (!CHECK_EVENT(EVENT_TEMP_CHANGE_REQ)) { // check if warming up flag is active
globalEvent = 0; // reset all event flags
} else { // when warming up or cooling dowm process is active
globalEvent = EVENT_TEMP_CHANGE_REQ; // reset all event flags excluding that
}
/* the time before go standby and soldering iron's temperature have an inverse relationship:
the higher termerature is, the less time it is allowed. */
m = map(temperature, LOW_TEMP_MARGIN, HIGH_TEMP_MARGIN, MAX_TIMEOUT_SEC, MIN_TIMEOUT_SEC);
cli();
// set values for timeout variables
dimCounter = TIME_BEFORE_DIM;
toCounter1 = m;
toCounter2 = LOW_POWER_MODE_DURATION;
sei();
}
ISR (PCINT0_vect) {
// dummy interrupt service routine
// called when one of pins D8 to D13 has changed
}
ISR(TIMER0_COMPA_vect){
static unsigned char mSec, // millisecond counter
quartSec; // 1/4 second counter
PORTC |= (1<<currentDigit); // turn off current LED tube
// ==========================================================================================
// Timeout counter routine
// ==========================================================================================
if (!(globalEvent & EVENT_TEMP_CHANGE_REQ)) { // count if no TEMP_CHANGE_REQ active
if (++mSec == 250) { // check for millisecond counter overflow
mSec = 0; // reset msec counter
if (++quartSec == 4) { // check for 1/4 sec counter overflow
quartSec = 0; // reset 1/4 sec counter
// timeout counting
// =======================[ TICK-TOCK Signaling ]==============================================
if (dimCounter > 0) if (--dimCounter == 0) OCR0B = MIN_BRIGHTNESS; // set display brightness to min.
if (toCounter1 > 0) { //decrease timout counter till 0
if (--toCounter1 != 0) {
// rise tick-tock flag
if (toCounter1 <= TICK_TOCK_COUNT) globalEvent |= EVENT_TICK_TOCK_REQ;
} else {
// rise 'go low power mode' flag
globalEvent |= EVENT_LOW_POWER_MODE | EVENT_ATTN_REQ;
}
} else { // in case low power mode is active
if (toCounter2 > 0) { // if timeout counter is greater than zero
if (--toCounter2 != 0) { // decrease timeout counter
if (toCounter2 <= TICK_TOCK_COUNT) globalEvent |= EVENT_TICK_TOCK_REQ;
} else { // if timeout counter is equal zero
globalEvent |= EVENT_STANDBY_MODE; // rise 'go stamdby' flag
}
}
}
// ==========================================================================================
}
}
}
}
ISR(TIMER0_COMPB_vect){
//
// displaying data, debouncing the button, tone generation
//
static unsigned char buttonState, // current button state
prevButtonState; // saved button state
static unsigned int keypressDuration, // button press duration
mSec; // millisecond counter
//================================================================================================
// display routine
//================================================================================================
if (++currentDigit == 3) currentDigit = 0; // for every digit...
PORTD = displayBuffer[currentDigit]; // send value
PORTC &= ~(1<<currentDigit); // and switch on
if (softTimer != 0) softTimer--; // decrease software timer
if (currentDigit == 0) { // on every 3rd call
//================================================================================================
// debouncing routine
//================================================================================================
buttonState <<= 1; // prepare to get a new button state bit
if ((PINB & (1<<PINB0)) == 0) buttonState |= 1; // check the button state and save it
if (buttonState == 0 || buttonState == 0xFF) { // check the button pressed or released
if (buttonState != prevButtonState) { // check the button state changed
if (buttonState == 0xFF) { // is it pressed?
globalEvent |= EVENT_BUTTON_PRESSED; // rise 'button pressed' flag
}
}
if (buttonState == 0xFF) { // when the button is pressed
if ((!(globalEvent & EVENT_STANDBY_MODE)) // and device is not in standby
&& (++keypressDuration == 650)) { // and the button is pressed long enough
globalEvent |= EVENT_STANDBY_MODE | EVENT_BUTTON_LONG; // rise standby flag
keypressDuration = 0; // reset keypress duration counter
}
} else {
keypressDuration = 0; // reset keypress duration counter
}
}
prevButtonState = buttonState; // save current button state
}
//================================================================================================
// Tone generation
//================================================================================================
if (bit_is_set(TCCR1A, COM1B0)) { // check if the tone generation is active
if (toneDuration > 0) { // check if duration counter is above zero
toneDuration--; // decrease the counter
} else { // in case of durationCounter == 0
cbi(TCCR1A, COM1B0); // stop the tone generation
}
}
if (CHECK_EVENT(EVENT_BEEPER_REQ) != 0) { // check the tone generation request is appeared
CLEAR_EVENT(EVENT_BEEPER_REQ); // reset request flag
sbi(TCCR1A, COM1B0); // enable tone signal output
}
if (dimCounter == 0) {
if (++mSec == 150) {
readPotReq = 1;
} else if (mSec > 299) {
mSec = 0;
displayUpdateReq = 1;
}
} else {
if (++mSec == 50) {
readPotReq = 1;
} else if (mSec > 99) {
mSec = 0;
displayUpdateReq = 1;
}
}
}
inline void setSoftTimer(unsigned int tValue) {
cli();
softTimer = tValue;
sei();
}
inline unsigned int getSoftTimer(void) {
// return soft timer downcounter value
unsigned int t;
cli();
t = softTimer;
sei();
return t;
}
void playTone(unsigned int pitchHz, unsigned int duration) {
// make sound
unsigned int pitch = (F_CPU / pitchHz - 2) / 2; // calculate timer settings to generate desired pitch
cli(); // disable interrupts to make atomic assignment
OCR1A = pitch; // set the new counter restart value
toneDuration = duration; // set the new tone duration value
sei(); // enable interrupst
SET_EVENT(EVENT_BEEPER_REQ); // send signal to the timer's ISR
}
#ifndef CALIBRATION_BUILD
void fillDisplayBuffer(int value, unsigned char padChar) {
// convert int to string and fill the display buffer
unsigned char i = 3; // digits at display
unsigned int dp_req = 0; // decimal point required flag
div_t res; // conversion divider
// check if it is the special value to shows the error message
if (-9999 == value) {
displayBuffer[0] = ~SIGN_E;
displayBuffer[1] = ~SIGN_r;
displayBuffer[2] = ~SIGN_r;
return;
}
// if passed value is smaller than 1000
if (value < 1000) {
dp_req = 1; // dot required
} else {
value /= 10; // devide value to fit to display
}
// padding left
if (value < 100) displayBuffer[0] = padChar;
if (value < 10) displayBuffer[1] = padChar;
// convert integer to string and place it to the buffer
do {
res = div(value, 10);
displayBuffer[--i] = codeTable[res.rem];
value = res.quot;
} while (value != 0 && i != 0);
// insert dot if required
if (dp_req) displayBuffer[1] &= ~SEG_DP;
}
#else
void fillDisplayBuffer(int value, unsigned char padChar) {
// convert int to string and fill the display buffer
unsigned char i = 3; // digits at display
unsigned int dp_req = 0; // decimal point required flag
div_t res; // conversion divider
// convert integer to string and place it to the buffer
do {
res = div(value, 10);
displayBuffer[--i] = codeTable[res.rem];
value = res.quot;
} while (value != 0 && i != 0);
}
#endif
void setup() {
// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=Out Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (1<<DDB5) | (0<<DDB4) | (0<<DDB3) | (1<<DDB2) | (1<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=0 Bit4=T Bit3=T Bit2=1 Bit1=0 Bit0=P
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (1<<PORTB2) | (0<<PORTB1) | (1<<PORTB0);
// Port C initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=Out
DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
// State: Bit6=T Bit5=P Bit4=P Bit3=T Bit2=0 Bit1=1 Bit0=1
PORTC=(0<<PORTC6) | (1<<PORTC5) | (1<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (1<<PORTC1) | (1<<PORTC0);
// Port D initialization
// Function: Bit7=Out Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRD=(1<<DDD7) | (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
// State: Bit7=1 Bit6=1 Bit5=1 Bit4=1 Bit3=1 Bit2=1 Bit1=1 Bit0=1
PORTD=(1<<PORTD7) | (1<<PORTD6) | (1<<PORTD5) | (1<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (1<<PORTD1) | (1<<PORTD0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 250,000 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 1 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
OCR0A=0xF9;
OCR0B = DEFAULT_BRIGHTNESS;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(1<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 0,5 ms
// Output Pulse(s):
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
OCR1AH=0x1F;
OCR1AL=0x3F;
// ADC initialization
// ADC Clock frequency: 125,000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: Off
// ADC4: On, ADC5: On
DIDR0=(0<<ADC5D) | (0<<ADC4D) | (1<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (0<<ADC0D);
ADMUX=(1<<REFS1) | (1<<REFS0) | 7;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
// go standby as soon as power is applied
SET_EVENT(EVENT_STANDBY_MODE);
}
#ifndef CALIBRATION_BUILD
unsigned int getOversampled(void) {
unsigned int sSum = 0;
// get 64 samples after the channel has become stable
for (int i = 0; i < 64; i++) {
sbi(ADCSRA, ADSC); // Start the AD conversion (it also clears ADIF flag as a side effect of 'sbi')
loop_until_bit_is_set(ADCSRA, ADIF); // wait for conversion complete
sSum += ADCW;
}
return sSum >> 4; // return averaged ADC result in 12 bit representation
}
#else
unsigned int getOversampled(void) {
unsigned int sSum;
unsigned long res = 0;
for (int i = 0; i < 16; i++) {
// get 64 samples after the channel has become stable
sSum = 0;
for (int j = 0; j < 64; j++) {
sbi(ADCSRA, ADSC); // Start the AD conversion (it also clears ADIF flag as a side effect of 'sbi')
loop_until_bit_is_set(ADCSRA, ADIF); // wait for conversion complete
sSum += ADCW;
}
res += sSum;
}
return res >> 8; // return averaged ADC result in 12 bit representation
}
#endif
unsigned int filterPot(unsigned int rawPot) {
static unsigned char potPrev;
if (rawPot == 0) {
potPrev = 0;
return 0;
}
unsigned char quot = rawPot / 15;
// check if pot's value is nearly the same
if (potPrev == quot) {
return quot + 1;
}
unsigned char rem = rawPot % 15;
if (rem > 4 && rem < 12) {
potPrev = quot;
return quot + 1;
}
// moving right
if (quot == potPrev + 1) {
if (rem < 5) {
return quot;
}
}
// moving left
if (potPrev = quot + 1) {
if (rem > 11) {
return potPrev + 1;
}
}
return quot + 1;
}
/*******************************************************************
***
*** DEBUG-ONLY SECTION
*** NOT USED IN NORMAL CODE FLOW
***
*******************************************************************/
#ifdef USE_DEBUG_CODE
float dV = REFERENCE_1V1 / 4096.0;
float getVoltage(void) {
return getOversampled() * dV;
}
float getSensorResistance(void) {
// get soldering iron's probe resistance
float v = getVoltage();
return R1 / (V_REF / v - 1.0);
}
#endif
/*********************** END OF DEBUG-ONLY SECTION ****************/
unsigned int findDifference(unsigned int a, unsigned int b) {
// compare 'a' and 'b' and return the difference
if (a == b) return 0; // return zerro in case a = b
if (a > b) return a - b; // self-exlplained code :)
return b - a;
}
unsigned char displayMode = 0, // data display selector
tickCounter = TICK_TOCK_COUNT, // countdown stage counter
skipMarker = 0; // skip counter
unsigned int sensorData, // soldering iron's temperature probe data
targetTemperature, // the temperature the soldering iron must be heated up to
wiperPosition, // ADC value from pot's middle contact
wPosPrev = 0, // temp wiperPosition var
displayValue, // data to be send to display
currentTemperature; // soldering iron temperature
#ifdef USE_DEBUG_CODE
float voltage; // the var for voltage measurement
#endif
#define DELAY(MS) cli(); softTimer = MS; sei(); while(softTimer != 0)
/*
**
** Main program loop
**
*/
void loop() {
if (CHECK_EVENT(EVENT_TICK_TOCK_REQ)) { // check the countdown flag is risen
tickCounter++; // increase stage counter
CLEAR_EVENT(EVENT_TICK_TOCK_REQ); // take down the flag
if (tickCounter < 5) { // check it is a first half of countdown
playTone(8000, 5); // play short high tone sound
} else { // increase loudness
if (tickCounter != TICK_TOCK_COUNT) { // check if it isn't last tick
displayMode = 3; // set show tick display mode
OCR0B = DEFAULT_BRIGHTNESS; // increase brightness
playTone(1000, 100); // make load beep
} else { // if it is last tick
playTone(1000, 800); // play the final beep
}
}
}
// ======================= STANDBY mode routine ==========================================
if (CHECK_EVENT(EVENT_STANDBY_MODE)) { // check the standby flag is risen
TURN_HEATER_OFF; // turn heater off
TURN_LED_OFF; // turn LED off
displayBuffer[0] = ~SIGN_BLANK; // blank display
displayBuffer[1] = ~SIGN_BLANK;
displayBuffer[2] = ~SIGN_BLANK;
if (CHECK_EVENT(EVENT_BUTTON_LONG)) {
playTone(1000, 800); // play long beep
setSoftTimer(800); // set soft timer to wait for signaling
}
tickCounter = 0; // reset tickCounter
// wait for the button is released and time is out
while ((PINB & (1<<PINB0)) || getSoftTimer());
TCCR0B &= ~0b111; // No clock source (Timer/Counter stopped)
cbi(TCCR1A, COM1B0); // disable speaker output
toneDuration = 0; // reset tone duration counter
PCMSK0 |= bit (PCINT0); // set pin 8 as interupt source
PCIFR |= bit (PCIF0); // clear any outstanding interrupts
PCICR |= bit (PCIE0); // enable pin change interrupts for D8 to D13
set_sleep_mode (SLEEP_MODE_PWR_DOWN); // set powerdown sleep mode
sleep_enable(); // allow enter into sleep mode
unsigned long int t = 0; // local keypress duration counter
while(1) { // go to endless standby loop
if ((PINB & (1<<PINB0)) == 0) { // check for button pressed
if (++t == 0x00300000) { // count keyperss duration and check it is long enough
PCMSK0 &= ~(1<<PCINT0); // disable pin 8 interrupt
PCICR &= ~(1<<PCIE0); // disable pin change interrupts for D8 to D13
break; // leave loop
}
} else { // if no kepress detected
t = 0; // reset keypress duration counter
sleep_cpu (); // go Sleep and wait for the interrupt
}
}
TCCR0B |= (1<<CS01) | (1<<CS00); // enable TIMER0 clocking
resetTimeout(LOW_TEMP_MARGIN); // reset timeout counters
displayMode = 0; // set display mode
targetTemperature = 0; // reset target temperature
playTone(1000, 600); // play greeting
#ifndef CALIBRATION_BUILD
#ifdef PREHEAT_ENABLE
DELAY(600)
preHeat();
playTone(6000, 20); // play greeting
DELAY(150);
playTone(6000, 20); // play greeting
#endif
#endif
CLEAR_EVENT(EVENT_BUTTON_LONG | EVENT_BUTTON_PRESSED);
}
// ======================= End of STANDBY mode routine =======================================
sensorData = getOversampled(); // get data from termal probe
if (readPotReq == 1) { // every 0.1 second
readPotReq = 0;
// reflect potentiometer's wiper position to temperature scale
ADMUX=(1<<REFS1) | (1<<REFS0) | 6; // set pot's ADC channel
//wiperPosition = map(getOversampled(), 0, 4095, LOW_TEMP_MARGIN, HIGH_TEMP_MARGIN);
wiperPosition = map(filterPot(getOversampled()) + LOW_TEMP_DEGREE / 100,
LOW_TEMP_DEGREE / 100, HIGH_TEMP_DEGREE / 100,
LOW_TEMP_MARGIN, HIGH_TEMP_MARGIN);
ADMUX=(1<<REFS1) | (1<<REFS0) | 7; // restore thermal probe ADC channel
// check if pot's data is different enough from target temperature
if (findDifference(targetTemperature, wiperPosition) > 7) {
OCR0B = DEFAULT_BRIGHTNESS; // increase display brightness
displayMode = 0; // set display mode
tickCounter = 0; // reset countdown var
targetTemperature = wiperPosition; // set new target temperature
setSoftTimer(1500); // set period for displaying target temperature instead of
// measured one
CLEAR_EVENT(EVENT_LOW_POWER_MODE); // leave low power mode
SET_EVENT(EVENT_TEMP_CHANGE_REQ); // set temperature changing flag
}
}
if (CHECK_EVENT(EVENT_BUTTON_PRESSED)) {// check keypress flag is set
displayMode = 0; // force display's main mode
CLEAR_EVENT(EVENT_BUTTON_PRESSED); // resed keypress flag
OCR0B = DEFAULT_BRIGHTNESS; // set display brighter
tickCounter = 0; // reset tickCounter
resetTimeout(sensorData); // re-calc timeout period
playTone(8000, 20); // make short audible 'click'
}
// represent current soldering iron temperature using the calibration data
currentTemperature = map(sensorData,
ADC_CALIBRATION_DATA_LOW,
ADC_CALIBRATION_DATA_HIGH,
CALIBRATION_TEMP_LOW,
CALIBRATION_TEMP_HIGH) / 10;
if (displayUpdateReq == 1) { // every 0.1 second
displayUpdateReq = 0; // reset flag
switch (displayMode) {
case 0:
if (!CHECK_EVENT(EVENT_TEMP_CHANGE_REQ)) { // if no changing temperature flag is set
if (findDifference(sensorData, targetTemperature) < 8) { // check the temperature is in the allowed boundaries
displayValue = map(targetTemperature,
LOW_TEMP_MARGIN,
HIGH_TEMP_MARGIN,
LOW_TEMP_DEGREE / 10,
HIGH_TEMP_DEGREE / 10); // use target temperature for displaying
} else { // in the case of temperature drift is high enough
if (CHECK_EVENT(EVENT_LOW_POWER_MODE)) { // if low power mode is active
if (findDifference(sensorData, LOW_TEMP_MARGIN) < 10 ) {
displayValue = LOW_TEMP_DEGREE / 10; // display fixed low margin degree value
} else {
displayValue = currentTemperature; // show real measured temperature
}
} else { // in main mode
#ifndef CALIBRATION_BUILD
displayValue = currentTemperature; // show real measured temperature
#else
displayValue = sensorData - 1000;
#endif
/*
displayValue = map(targetTemperature,
LOW_TEMP_MARGIN,
HIGH_TEMP_MARGIN,
LOW_TEMP_DEGREE / 10,
HIGH_TEMP_DEGREE / 10); // use target temperature for displaying
*/
}
}
} else { // in heating up or cooling down stage
if (!getSoftTimer()) { // if target temperature is not changed recently
//displayValue = currentTemperature; // display real measured temperature
#ifndef CALIBRATION_BUILD
displayValue = currentTemperature; // show real measured temperature
#else
displayValue = sensorData - 1000;
#endif
} else { // target temperature just changed
displayValue = map(wiperPosition,
LOW_TEMP_MARGIN,
HIGH_TEMP_MARGIN,
LOW_TEMP_DEGREE / 10,
HIGH_TEMP_DEGREE / 10); // show target temperature
}
}
break;
/******************************************************************
***
***
*** DEBUG ONLY SECTION
***
***
*******************************************************************/
#ifdef USE_DEBUG_CODE
case 1:
displayValue = (getVoltage(3) - 1.0) * 10000;
break;
case 2:
displayValue = (getSensorResistance()) * 10;
break;
#endif
/********************* END OF DEBUG CODE **************************/
case 3:
displayValue = TICK_TOCK_COUNT - tickCounter; // show countdown values
break;
default:
break;
}
fillDisplayBuffer(displayValue, ~SIGN_BLANK); // send data to the display
}
if (CHECK_EVENT(EVENT_LOW_POWER_MODE)) { // if low power mode active
if (CHECK_EVENT(EVENT_ATTN_REQ)) { // check if it is first occurrence
CLEAR_EVENT(EVENT_ATTN_REQ); // down flag
tickCounter = 0; // reset tick counter
OCR0B = MIN_BRIGHTNESS; // lower display brightness
displayMode = 0; // set main display mode
}
wiperPosition = LOW_TEMP_MARGIN; // force targed temperature to 185C degree
}
/*****************************************************************
**
** HEATER CONTROL SECTION
**
*****************************************************************/
if (sensorData < wiperPosition) { // check if current temperature is lower than target one
TURN_HEATER_ON; // force heating up
TURN_LED_ON; // toggle LED on
} else{ // the current temperature is equal to target one or above
TURN_HEATER_OFF; // disable heating up
TURN_LED_OFF; // toggle LED off
}
/*****************************************************************/
// check if it is temperature changing mode
if (CHECK_EVENT(EVENT_TEMP_CHANGE_REQ) != 0) {
// check if temperature target has reached
if (findDifference(sensorData, wiperPosition) < 4) {
CLEAR_EVENT(EVENT_TEMP_CHANGE_REQ);
resetTimeout(sensorData); // recalculate timeout
playTone(4000, 50); // play 'temperature matched' sound mark
}
}
}
#ifdef PREHEAT_ENABLE
void preHeat(void) {
unsigned int sData;
// check if current temperatue low enough
if (getOversampled() < LOW_TEMP_MARGIN) {
// save current TIM1 settings
unsigned int sTCCR1A = TCCR1A;
unsigned int sTCCR1B = TCCR1B;
// unsigned int sOCR1AL = OCR1AL;
// unsigned int sOCR1AH = OCR1AH;
// reinit timer in PWM mode
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (1<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
sbi(ADMUX, 1);
for (int i = 20; i <= 100; i++) {
cbi(TCCR1A, COM1A1); // disable PWM output
DELAY(2); // wait till the probe becomes stable
sData = getOversampled();
OCR1A = 5 * i; // set new duty cycle ratio (i is equal duty cycle)
sbi(TCCR1A, COM1A1); // enable PWM output
if (sData > LOW_TEMP_MARGIN) break; // go away if preheating target is reached
fillDisplayBuffer(map(sData,
ADC_CALIBRATION_DATA_LOW,
ADC_CALIBRATION_DATA_HIGH,
CALIBRATION_TEMP_LOW,
CALIBRATION_TEMP_HIGH) / 10,
~SIGN_BLANK); // display current temperature
for (int k = 0; k < 10; k++) {
// show preheating blink
TURN_LED_ON;
DELAY(3);
TURN_LED_OFF;
DELAY(7);
}
}
TURN_LED_OFF;
// restore timer settings
OCR1A = 0;
TCCR1A = sTCCR1A;
TCCR1B = sTCCR1B;
// OCR1AL = sOCR1AL;
// OCR1AH = sOCR1AH;
TURN_HEATER_OFF;
}
}
#endif
Спасибо, a5021. Все очень доходчиво. Попробовал откалибровать с обычным термометром. На температурах до 300 градусов присутствует погрешность. Ближе к 400 градусов погрешности почти нет. Видимо из-за того, что калибровал обычным термометром. Попробую найти лабораторный термометр с десятыми градусов и еще раз откалибровать.
Я задумывался над тем, чтобы развести еще и smd-версию, но остановило опасение, что она не будет востребована. Трассировка хоть и интересный, но довольно длительный процесс, а времени, как обычно, ни на что не хватает. В принципе, если общественность проявит более активный интерес, может и сподоблюсь. Но тут важным становится вопрос, в каких размерах это все делать. Для себя я делаю все максимально мелко и тонко, но это требует определенной квалификации при изготовлении платы, что может вызвать трудности у начинающих. Еще вопрос конструктивов и размерносей компонентов не совсем однозначен. Если я разведу под свои компоненты, то это наверняка приведет к трудностям с поиском того же самого при повторении кем-то другим.
Боюсь это будет весьма проблематично, прежде всего из-за сложностей с измерением этой самой температуры на кончике. Усилий это может потребовать значительно больше, чем полученных таким образом выгод.
Боюсь это будет весьма проблематично, прежде всего из-за сложностей с измерением этой самой температуры на кончике. Усилий это может потребовать значительно больше, чем полученных таким образом выгод.
А почему сложно? термопарой мультиметра например отлично меряется. Соответственно у каждого жала при одной и тойже температуре разные калибровочные значения. Хранить можно прям в скетче массивом. Выбирать (например) удержанием кнопки + потенциомерт вправо - влево
Термопарой, подключенной к мультиметру, получится измерить только "стреднюю температуру по больнице". Даже не уверен, что она покажет разную температуру для разных жал. Для калибровки "взрослых" паяльных станций в комплекте к ним идут специальные устройства для измерения темпертуры именно жала и существуют требования по организации таких измерений. Кончик жала может изменять температуру на десятки градусов только от одного движения воздуха в помещении. Как я говорил еще в самом первом сообщении, приходится иметь дело лишь с приблизительными температурами в зоне пайке и с этим, по большому счету, ничего не поделать.
Большое спасибо a5021 за данный проект, сделал, запустил (не без проблем, но это из-за своих ошибок) - доволен как слон. НО! В языке программирования я очень начинающий и не смог понять как "раскоментировать" и соответственно не могу откалибровать паяльник. Не мог бы кто нибуть выложить скетч с раскомментированным определением CALIBRATION_BUILD. Буду премного благодарен!
Еще пара вопросов: в каких случаях издается звуковой сигнал? При питании данной схемы от БП компьютера можно обойтись без кренки и питать от +5 вольт БП?
Раскомментировать -- значит убрать знак(и) комментария. В данном случае речь идет о строке № 26. Уберите два слеша ("//") в начале строки и директива будет раскомментирована. Чтобы закомментировать обратно, эти два слеша надо вернуть. Вот и вся премудрость.
Без кренки обойтись можно, но подаваемые +5в от БП не должны иметь больших пульсаций. Шум по линии +5в может плохо влиять на точность измерений температуры и, как следствие, на стабильность показаний на индикаторе.
Подать +5в напрямую от БП можно, если не запаивать эту самую кренку, а припаять провод прямо вместо ее вывода №3. Весьма не лишним в этом случае будет увеличить емкость конденсатора С5 из расчета, чем больше, тем лучше.
Диод там был поставлен исходя из двух соображений: а) шунтировать диодом индуктивную нагрузка (динамик, в данном случае) является хорошим тоном, чтобы потом не разбираться с непонятными переходными процессами; б) динамик может оказаться пьезоэлектрическим (иногда их по виду отличить сложно), который при механическом воздействии на него (удар, падение) может сам являться генератором значительных напряжений, достаточных, чтобы спалить транзистор, нагрузкой для которого он является.
Если по каким-то соображениям вы не хотите устанавливать диод, можно не устанавливать. Непосредственно на функционал это не влияет. Диод выполняет защитные функции и только лишь в некоторых случаях.
Добрый день. Сделал каллибровку по вашей методике, получил значения 36,2 (градуса) - 993 (на дисплее), и 85 - 213. В какие строки кода внести это значения?
Все прошилось, по личным ощущениям температура жала стало грется сильнее, но точнее сказать пока не могу - завтра возьму у знакомого дистанционный термометр - измерю точнее. Есть такая" шероховатость" -при крайнем положении переменика температура на индикаторе скачком снижается к минимальной. Переменик 12 ком. Это можно исправить?
И неплохо бы увеличить время перехода паяльника в "сон", у меня оно около 5 минут. Попутно вопрос - переход в сон происходит когда регулировку не трогаем или при отсутствии резких изменений температуры жала? Типа не паяем - температура почти постоянная, изменения в пару градусов.
С переменником вы сурово поступили. При такой замене вы отрезали 9/10 диапазона регулирования в верхней части. Чтобы использовать переменник величиной 1ком, резисторы R20 и R21 должны быть 270ом и 1ком соответственно.
Переход в сон зависит от температуры жала и составляет 15 секунд при крайне правом положении переменника и один час при крайне левом. Промежуточные положения "размазаны" пропорционально. Крайние значиния для диапазона заданы определениями в тексте скетча:
// min timeout in seconds
#define MIN_TIMEOUT_SEC 15
// max timeout in seconds
#define MAX_TIMEOUT_SEC (60 * 60)
Условием для перехода в "сон" является отсутствие воздействия на органы управления (переменник, кнопка) или резких изменений температуры. Последнее не является режимом детектирования пайки. Паялка уйдет в сон не зависимо от того, происходит пайка или нет.
Приношу свои извинения, неправильно посчитал значение переменика, на нем обозначение В103 - это все таки 10кОм. Но температура при приближении к крайнему максимальному положению падает до минимальной. Напряжение на среднем выводе переменика меняется от 0 вольт до 0.98.
Для идеального случая оно должно меняться с нуля до 1.1 вольта (величина внутреннего опорного напряжения атмеги), но так как идеального ничего не существует, а существует разброс в величинах сопротивлений R20, R21 и самого переменника, то 0.98 -- это, пусть и не лучший, но вполне допустимый результат. Чуть снизится верхний предел регулировки. А вот почему падает температура на правом краю, тут пока загадка. Покопаюсь на досуге в исходниках. Есть нехорошее подозрение, что это может оказаться переполнением какой-то переменной.
А как ФАКТИЧЕСКИ, не отображаемую на индикаторе, увеличить температуру жала? Т.е. на индикаторе у меня 439 градусов (больше не устанавливается - сбрасывается) а по ощущениям намного меньше. Измерить температуру времено не могу - приятель только на днях термометр принесет.
Извините что не по теме, но хочу задать один вопрос в сило своей не грамотности в области электроники.
Я что-то не догоняю или использование ШИМ в регулировке температуры фена по схеме Ильи c MOC3061 не возможно?
Просто на основе похожей схемы собрал диммер к ESP8266. В режиме реле работает отлично, а вот диммировать лампу накаливания не хочет (хотя замерял сопротивление через BTA16 изменяется от 5кОм и выше). Или MOC3061 с его детектором перехода через 0 тут ни при чем и я просто сделал что-то не так?
Тест на нем проводил - последовательно 2 лампы 12В 100Вт. Зажглись, ток выдал в районе 3,96А, в защиту не ушел, но хорошо гудел. Для паяльника должен подойти (для чего я собственно и заказывал).
Второй вопрос. Ардуины на борту имеют стабилизатор, на моей Мини Про LG50 - 500ма, до 12В. Вместе например с КРЕН 9В можно распределить тепло и уменьшить количество радиаторов. Токи вроде небольшие.
БП симпатичный и по деньгам вполне неплохо. Если он держит заявленные характеристики, то это как раз то, что нужно. Даже если будет срабатывать защита при холодном включении, теперь есть ШИМ-разогрев, который купирует эту проблему.
Насчет набортного регулятора ардуины -- использовать его по предложенной вами схеме проблематично. Помимо самого ардуины есть еще остальная схема, которая так же расчитана на питание от 5 вольт. Если туда подать 9 вольт, то это напряжение через светодиоды индикатора окажется на ногах ардуины и даже если не сожжет сразу, то начнет "поднимать" его, т.к. выходы внутри атмеги через защитные диоды соеденины с шиной +5v.
Насчет разогрева линейного регулятора (7805) хочу заметить, что несмотря на то, что греется он весьма ощутимо, температура прибора не выходит за рамки допустимых эксплуатационных пределов. Монтаж с использованием платы в качестве радиатора в данном случае допускает и большую тепловую нагрузку. Если не смотря на это кому-то хочется, чтобы вообще ничего не грелось, то нет никаих проблем в дырки от 7805 запаять провода с внешнего импульсного преобразователя. Так популярная понижайка на lm2596
вписывается сюда без каких бы то нибыло вопросов.
dobrman пишет:
Я что-то не догоняю или использование ШИМ в регулировке температуры фена по схеме Ильи c MOC3061 не возможно?
Он включается только при переходе волны через ноль и всякий шим в другое время ему по барабану.
Frolv пишет:
А как ФАКТИЧЕСКИ, не отображаемую на индикаторе, увеличить температуру жала?
По стабилизатору на борту я имел в виду, что даем 9В (можно даже 12В) на порт Vin или RAW (в зависимости от модели Ардуино), а с VCC отй же Ардуины получаем те же стабилизированные 5В до 500ма. Не знаю, как по току дисплей, но ток делителя напряжения примерно 2ма, регулятора еще меньше.
Но со step-down конвертером конечно же будет лучше. Только его еще заказать и дождаться нужно.
Мне интересный вопрос - не думали над защитой от зависания Ардуины при открытом полевике? Например, глобальный сброс при достижении критического сопротивления термистора.
Кстати, вспомнил еще один вопрос - зачем использовать опорный источник напряжения, если можно измерить фактическое напряжение приходящих 5В?
а с VCC отй же Ардуины получаем те же стабилизированные 5В до 500ма. Не знаю, как по току дисплей, но ток делителя напряжения примерно 2ма, регулятора еще меньше.
Ток через дисплей в пике составляет 7сегментов * 20ма = 140ма. Сам ардуино кушает 30-40ма. Добавим потребление прочих элементов схемы и в сумме получится где-то 200ма. Ток кажется вполне приемлемым. Но это только до того, как начнем считать мощность выделяемую в тепло на линейном стабилизаторе ардуины. А она будет выглядеть так: P= (Vin - Vout) * Iout. Для наших цифр это получится (12-5) * 0.2 = 1.4W, что является трижды запредельной величиной для того типа корпуса, в котором регулятор распаян на ардуине. Регулятору в таких условиях скорее всего захочется выпаяться (с этим у него проблем не возникнет) и убежать. :)
Цитата:
Мне интересный вопрос - не думали над защитой от зависания Ардуины при открытом полевике? Например, глобальный сброс при достижении критического сопротивления термистора.
По хорошему, надо дописать использование аппаратного ватчдога ардуины в скетче. Только это будет не защита от неконтролируемого нагрева паяльника, а просто от зависания ардуины. Но тут есть подводные грабли, т.к. разработчики ардуины сделали все возможное, чтобы сделать использование ватчдога максимально сложным. Чтобы быстро выпустить рабочую версию скетча, от многих задумок, которые там должны, по-хорошему, присуствовать, мне пришлось, как минимум на время, отказаться.
Использование аппаратной защиты тянет за собой усложнение схемы и вызывает лишние сложности с повторением, особенно начинающими. По своему опыту эксплуатации различных самодельных паялок я знаю, что неконтролируемый разогрев паяльника ситуация довольно редкая. У меня это случалось только во время разработки и исключительно из-за собственной невнимательности. Риск того, что правильно собранная схема при подаче на нее рекомендованных напряжений самопроизвольно выйдет из строя не очень велик, т.ч. взвесив плюсы и минусы, от реализации аппаратной защиты я решил отказаться.
Если кому-то захочется повышенной надежности, то можно добавить в схему компаратор с порогом 1.2в и подключить его параллельно входу АЦП ардуины. На выходе компаратора будет формироваться аварийный сигнал в случае, если нагрев паяльника превысил допустимый диапазон.
Цитата:
Кстати, вспомнил еще один вопрос - зачем использовать опорный источник напряжения, если можно измерить фактическое напряжение приходящих 5В?
В этом случае мы поимеем сразу несколько минусов по сравнению с нынешней схемой. Имеются достаточно значимые основания, чтобы так не делать, но чтобы еще больше не загромождать объяснение, просто встаньте осциллографом на шину +5в и посмотрите, что на ней твориться во время работы схемы. Если это употребить в качестве опорного напряжения, то о точности удержания температуры лучше 10-20 градусов можно даже и не заикаться.
Попробую объяснит - это про температуру. У меня по индикатору температура не устанавливается выше 439 градусов. По моим ощущениям (возможно ошибочным) это не соответствует действительности - температура на жале паяльника ниже. Калибровку по вашей методике делал - не сильно помогло. Можно ли поправить код таким образом что бы поднять температуру? Т.е. по индикатору предположим 300, а на жале - 350.
По переходу паяльника в "сон". Как то странно это происходит. На максимальной температуре паяльник лежит на подставке несколько десятка два минут - в "сон" не переключается, начал пользоваться (паять) плату - через полминуты запищал сигнал начала перехода в "сон" Может лучше режим "сон" назначить на кнопку? Нажал - паяльник уснул, через несколько минут (предположим минут 10-15) нагрев вообще выключился.
Мой совет, сначала все-таки установите сколь нибудь более достоверно, что ошибка индикации температуры имеет место. Я бы вот на глаз вряд ли смог различать температуры пяльника 440 и 380 градусов, скажем. И что вы, если не секрет, паяете при такой температуре жала? Я, например, уже не помню, когда последний раз что-то паял с температурой больше 320 градусов.
Если вам непременно хочется, чтобы паяльник грел сильнее, уменьшите значение ADC_CALIBRATION_DATA_HIGH
Режим сна задуман, как средство против забывчивости. Оставлять паяльник включенным на долгое время все-таки не лучшая идея. Если в сон уходить только по кнопке, то велик шанс получить ситуацию, когда и на кнопку забудешь нажать, а паяльник будет сутки барабанить, дожигая жало.
Подскажите правильно ли будет подключить корпус паяльника на общий минус и потом уже через конденсатор к общему минусу подключить заземляющий контур?
Что такое заземление?
это защита от поражения электрическим током человека.
Что подключается к заземлению?
Все нетоковедущие части электроустановки, которые могут оказаться под напряжением.
Из этого следует, что к заземлению нужно подключать все металлические части корпуса, которые могут оказаться под напряжением. конденсатор на землю, это не заземление.
Скетч править -- это само собой. Сейчас глянул, всего придется вносить изменения в три строки. Одна строка (номер 207) в обработчике прерывания COMPA, и две (261-262) в COMPB. Смысл простой -- там, где для общего анода бит выставляется, для общего катода он должен сбрасываться и наоборот.
А получилось что-то с экранированием?
Не стал городить поддоны. В принципе кроме как дрожания символов паяние не страдает. А это главное. Думаю просто вынести плату в отдельный маленький корпус (благо не греется ничего) и питаль от ноутбучного БП.
В принципе, если предполагаются тяжелые помеховые условия эксплуатации, как в случае с "фонящим" блоком питания, то можно режим индикации заданной температуры, вместо измеренной, выбрать в качестве основного. Даже если нагреватель будет отрабатывать не совсем точно, то за счет интерности жала температура на кончике будет в значительной степени усредняться близ заданного значения.
Подскажите какой мощности резисторы в цепи управления нагревателем фена в схеме ? - http://arduino.ru/forum/proekty/payalnaya-stantsiya-iz-arduino?page=1#comment-86493
Я поставил 0,125Вт, работает. Цвет не поменяли, рукой подлезть потрогать не подлезть. Эти сопротивления работают в короткий промежуток времени , пока не включится симистор, а это происходит в начале полупериода. Так что все гут!
Порядком достало, что плата на проводах по столу ездит, решил прикрутить на общее основнание и закрепить кабель. Основанием послужила какая-то старая и давно распаянная на запчасти плата неизвестно от чего. Вот, что получилось:
Сверху от паялки можно наблюдать плату преобразователя (DC-DC) 12 вольт на 24 вольта. Так как питание от настольного компа у меня основное, а после замеров скорости нагрева выяснилось, что разогрев с 12 вольт получается долгий, то решил дополнить устройство бустером:
Данная повышайка собрана на контроллере UC3843 по схеме близкой к референсной. Дроссель намотан на кольце со старой материнской платы. Материал №52, цвет салатовый с синим, размеры 15,5 х 8,5 х 6 мм. Использовался сложенный вдвое провод диаметром 0,5мм, который наматывался без предварительного расчета из соображений "сколько влезет". Измеренная индуктивность в итоге составила 22мкГн, что вполне устроило. Изначально были представления, что кольцо должно быть существенно больше размерами, т.к. планировалось снимать с него более 50 Ватт мощности, но эксперимент показал, что и это двольно компактное кольцо вполне работоспособно при нагреве до 50-60 градусов во время работы.
Так как микросхема у меня была в корпусе под поверхностный монтаж, то основная часть деталей также размещена на стороне дорожек:
Мосфет с допустимым током до 80 ампер выдран с той же материнки. Большинство деталей надерганы с плат из ящика с радиохламом. В общем, получилось довольно бюджетно и приемлемо по параметрам. Если у кого-то возникнет желание повторить, могу выложить схему и чертеж платы.
Будьте добры выслать схему и чертеж на мыло shakalby@mail.ru
Спасибо большое заранее!!!
Проще будет прямо здесь разместить. Вот схема:
Некоторые элементы я забрал в рамку из пунктира, чтобы пометить, что присутствие этих деталей желательно, но если по каким-то причинам нет возможности их раздобыть, то можно не ставить. Единственное уточнение -- резистор R4 не просто не устанавливать, а заменить перемычкой.
Полуваттные резисторы R6-R9 включены в параллель, чтобы набрать общее сопротивление 0.025 ома. Единичных сопротивлений столь малой величины среди запасов и в продаже отыскать не удалось, т.ч. пришлось параллелить то, что оказалось доступно. В принципе, там можно поставить одно сопротивление 0.025 ома мощностью 1-2 ватта. Столь экзотический резистор в схеме присутствует для ограничения максимального тока через ключ. Если поставить резистор с большим номиналом, то преобразователь будет давать просадку напряжения при пиковых нагрузках, если номинал выбрать ниже, то увеличится нагрузка на источник.
Диод D2 -- это Шоттки с рабочим током не ниже 3 ампер (например, B340, SS34, B34, SK34 и т.п.). На самом деле пиковые нагрузки на этот диод в данной схеме существенно выше, но у большинства производителей данные приборы держат в пике по 80-120 ампер, т.ч. их использование вполне тут оправдано. В принципе, величина тока в большинстве случаев ограничивается тепловыделением кристала и если обеспечить должный теплоотвод, то рабочий ток можно смело задирать.
Мосфет лучше выбирать с минимальным значением сопротивления канала в открытом состоянии (Rds) и на напряжение не ниже 30 вольт. Хорошо себя показали мощные мосфеты с материнских плат.
Вообще, данную повышайку можно использовать не только применительно к паялке, но и для любых других надобностей, где возникает потребность повысить напряжение. На вход можно подавать любое напряжение из диапазона 9в..30в, а с выхода получать не ниже, чем входное. По похожим схемам делают бустеры вольт до четырехсот и выше. Разумеется, детали силовой части должны быть расчитаны на подобные напряжения.
Выходное напряжение определяется величинами R10, R11+R12 в резиситвном делителе. Можно их рассчитать по формуле V(out) = 2.5 * (1 + R10/(R11 + R12)), но я как-то привык пользоваться онлайн-калькулятором. Поле "Input Voltage" оставляем пустым, в поле "Output voltage" заносим константу 2.5, а R1 и R2 -- это R10 и R11+R12 с вышеприведенной схемы. "Играя" значениями в полях R1 и R2 можно подобрать номиналы делителя на желаемое выходное напряжение.
Если вникать в тонкости схемы нет желания, а просто хочется повторить устройство, то вот вариант схемы и платы в формате протеуса. Размеры платы специально сделаны попросторнее, т.к. пустые участки меди служат радиатором, отводя тепло от греющихся элементов -- диода и мосфета.
Здравствуйте. Собрал себе паяльную станцию по проекту a5021 (за что ему отдельное большое спасибо). Споткнулся на калибровке. Не могу понять, как (или где) увидеть значения getOversampled(). Может я задаю глупый вопрос, но до этого проекта с ардуиной не имел дела. А после прочтения форума появилось желание для начала просто повторить. Поэтому, если не трудно разъясните более подробно. И после того, как я выясню значения getOversampled(), нужно заново заливать скетч в ардуину?
Я уже где-то выше писал, что, по идее, процедура калибровки должна быть встроенная, но пока у меня так и не хватило сил и времени, чтобы написать ее в полном объеме. Поэтому на данный момент калибровка страдает изрядной горбатостью, когда нужно сначала выяснить эти самые значения getOversampled(), затем внести полученные значения в исходники и перезалить скетч.
О том, как проще выяснить, что там getOversampled() возвращает: мне в голову не пришло ничего лучше, как сделать довольно грубый хак, чтобы скетч показывал эти значения на основном индикаторе. Это не самое лучшее решение, но зато быстрое. В общем, если раскомментировать определение CALIBRATION_BUILD в тексте скетча, что я прикладываю ниже, то после его сборки и заливки паялка потеряет почти весь свой функционал, перестанет включать нагреватель вообще, но зато будет показывать на дисплее три последние цифры значения, возвращаемого функцией getOversampled(). Старшая цифра без сильного нагрева всегда 1, а если греть дальше, то можно отследить смену старшего разряда по переходу значений на индикаторе через ноль.
Тут подумалось, что для калибровки, возможно, удобно будет воспользоваться медицинским термометром, как прибором достаточно точным в рамках некоторого диапазона. Процедура может быть следующей: заливаем в паялку скетч с раскомментированным определением CALIBRATION_BUILD. Наливаем в некую посудину теплой воды, по температуре близкой к температуре человеческого тела. Посудину лучше чем-нибудь укутать, чтобы быстро не остывала. Раскручиваем паяльник, чтобы нагреватель торчал наружу и помещаем его (нагреватель) в воду. В эту же воду помещаем медицинский термометр. Включаем паялку. Ждем некоторое время, пока все прогреется и записываем значения с термометра и дисплея паялки на бумажку. Выливаем воду и убираем медицинский термометр. Теперь берем другой термометр, с помощью которого можно измерять температуту горячей воды, наливаем в посудину кипяток из чайника и схоожим образом фиксируем новые значения. Переносим числа с бумажки в текст скетча, выносим CALIBRATION_BUILD в комментарии и перезаливаем скетч. Вытираем нагреватель, скручиваем паяльник. Все, паялка откалибрована и готова к работе.
Ну и сам скетч в новой версии. Никаких новых фич, кроме возможности сборки калибровочного билда в нем нет, т.ч. тем, кто уже пользуется данной паялкой смысла его заливать никакого нет.
Спасибо, a5021. Все очень доходчиво. Попробовал откалибровать с обычным термометром. На температурах до 300 градусов присутствует погрешность. Ближе к 400 градусов погрешности почти нет. Видимо из-за того, что калибровал обычным термометром. Попробую найти лабораторный термометр с десятыми градусов и еще раз откалибровать.
Давно не заходил на форум. А тут уже и новая прошивка.
Прошил, проверил. Стабильнее показывать стало. Раньше в пределах градуса-трех менялось, сейчас стоит как вкопанное.
Спасибо a5021.
По исполнению, запихнул в корпус от внешнего харда, на 2.5" работает уже несколько месяцев. Безумно выручает.
Питание от БП ноубука, 19В 4.5A
Добрый день. Собираю такую станцию и есть просьба - кто-нибуть развел печатную плату под SMD? Не поделитесь?
Я задумывался над тем, чтобы развести еще и smd-версию, но остановило опасение, что она не будет востребована. Трассировка хоть и интересный, но довольно длительный процесс, а времени, как обычно, ни на что не хватает. В принципе, если общественность проявит более активный интерес, может и сподоблюсь. Но тут важным становится вопрос, в каких размерах это все делать. Для себя я делаю все максимально мелко и тонко, но это требует определенной квалификации при изготовлении платы, что может вызвать трудности у начинающих. Еще вопрос конструктивов и размерносей компонентов не совсем однозначен. Если я разведу под свои компоненты, то это наверняка приведет к трудностям с поиском того же самого при повторении кем-то другим.
Интересно было бы сделать "пресеты" с разными калибровками под разные жала. Ведь явно у толстого и тонкого жала температура на кончике будет разной.
Боюсь это будет весьма проблематично, прежде всего из-за сложностей с измерением этой самой температуры на кончике. Усилий это может потребовать значительно больше, чем полученных таким образом выгод.
Боюсь это будет весьма проблематично, прежде всего из-за сложностей с измерением этой самой температуры на кончике. Усилий это может потребовать значительно больше, чем полученных таким образом выгод.
А почему сложно? термопарой мультиметра например отлично меряется. Соответственно у каждого жала при одной и тойже температуре разные калибровочные значения. Хранить можно прям в скетче массивом. Выбирать (например) удержанием кнопки + потенциомерт вправо - влево
Термопарой, подключенной к мультиметру, получится измерить только "стреднюю температуру по больнице". Даже не уверен, что она покажет разную температуру для разных жал. Для калибровки "взрослых" паяльных станций в комплекте к ним идут специальные устройства для измерения темпертуры именно жала и существуют требования по организации таких измерений. Кончик жала может изменять температуру на десятки градусов только от одного движения воздуха в помещении. Как я говорил еще в самом первом сообщении, приходится иметь дело лишь с приблизительными температурами в зоне пайке и с этим, по большому счету, ничего не поделать.
Ну тогда ладно :)
Большое спасибо a5021 за данный проект, сделал, запустил (не без проблем, но это из-за своих ошибок) - доволен как слон. НО! В языке программирования я очень начинающий и не смог понять как "раскоментировать" и соответственно не могу откалибровать паяльник. Не мог бы кто нибуть выложить скетч с раскомментированным определением CALIBRATION_BUILD. Буду премного благодарен!
Еще пара вопросов: в каких случаях издается звуковой сигнал? При питании данной схемы от БП компьютера можно обойтись без кренки и питать от +5 вольт БП?
Раскомментировать -- значит убрать знак(и) комментария. В данном случае речь идет о строке № 26. Уберите два слеша ("//") в начале строки и директива будет раскомментирована. Чтобы закомментировать обратно, эти два слеша надо вернуть. Вот и вся премудрость.
Без кренки обойтись можно, но подаваемые +5в от БП не должны иметь больших пульсаций. Шум по линии +5в может плохо влиять на точность измерений температуры и, как следствие, на стабильность показаний на индикаторе.
Подать +5в напрямую от БП можно, если не запаивать эту самую кренку, а припаять провод прямо вместо ее вывода №3. Весьма не лишним в этом случае будет увеличить емкость конденсатора С5 из расчета, чем больше, тем лучше.
a5021, у меня к вам вопрос по схеме. Зачем нужен диод D2 в цепи динамика? И нужен ли он там вообще?
Диод там был поставлен исходя из двух соображений: а) шунтировать диодом индуктивную нагрузка (динамик, в данном случае) является хорошим тоном, чтобы потом не разбираться с непонятными переходными процессами; б) динамик может оказаться пьезоэлектрическим (иногда их по виду отличить сложно), который при механическом воздействии на него (удар, падение) может сам являться генератором значительных напряжений, достаточных, чтобы спалить транзистор, нагрузкой для которого он является.
Если по каким-то соображениям вы не хотите устанавливать диод, можно не устанавливать. Непосредственно на функционал это не влияет. Диод выполняет защитные функции и только лишь в некоторых случаях.
Благодарю за развёрнутый ответ.
Добрый день. Сделал каллибровку по вашей методике, получил значения 36,2 (градуса) - 993 (на дисплее), и 85 - 213. В какие строки кода внести это значения?
Значения нужно занести в строки 44 - 47. Предполагаю, что в вашем случае они будут выглядеть так:
Огромнейшее спасибо!
Расскажите потом, что получилось, если не сложно.
Помогите " коллегам" ;)
http://we.easyelectronics.ru/Tools/lukey-702-pechalka-.html
Все прошилось, по личным ощущениям температура жала стало грется сильнее, но точнее сказать пока не могу - завтра возьму у знакомого дистанционный термометр - измерю точнее. Есть такая" шероховатость" -при крайнем положении переменика температура на индикаторе скачком снижается к минимальной. Переменик 12 ком. Это можно исправить?
И неплохо бы увеличить время перехода паяльника в "сон", у меня оно около 5 минут. Попутно вопрос - переход в сон происходит когда регулировку не трогаем или при отсутствии резких изменений температуры жала? Типа не паяем - температура почти постоянная, изменения в пару градусов.
Извиняюсь - переменик 1 (один) кОм!!!
С переменником вы сурово поступили. При такой замене вы отрезали 9/10 диапазона регулирования в верхней части. Чтобы использовать переменник величиной 1ком, резисторы R20 и R21 должны быть 270ом и 1ком соответственно.
Переход в сон зависит от температуры жала и составляет 15 секунд при крайне правом положении переменника и один час при крайне левом. Промежуточные положения "размазаны" пропорционально. Крайние значиния для диапазона заданы определениями в тексте скетча:
Условием для перехода в "сон" является отсутствие воздействия на органы управления (переменник, кнопка) или резких изменений температуры. Последнее не является режимом детектирования пайки. Паялка уйдет в сон не зависимо от того, происходит пайка или нет.
Приношу свои извинения, неправильно посчитал значение переменика, на нем обозначение В103 - это все таки 10кОм. Но температура при приближении к крайнему максимальному положению падает до минимальной. Напряжение на среднем выводе переменика меняется от 0 вольт до 0.98.
Для идеального случая оно должно меняться с нуля до 1.1 вольта (величина внутреннего опорного напряжения атмеги), но так как идеального ничего не существует, а существует разброс в величинах сопротивлений R20, R21 и самого переменника, то 0.98 -- это, пусть и не лучший, но вполне допустимый результат. Чуть снизится верхний предел регулировки. А вот почему падает температура на правом краю, тут пока загадка. Покопаюсь на досуге в исходниках. Есть нехорошее подозрение, что это может оказаться переполнением какой-то переменной.
А как ФАКТИЧЕСКИ, не отображаемую на индикаторе, увеличить температуру жала? Т.е. на индикаторе у меня 439 градусов (больше не устанавливается - сбрасывается) а по ощущениям намного меньше. Измерить температуру времено не могу - приятель только на днях термометр принесет.
Извините что не по теме, но хочу задать один вопрос в сило своей не грамотности в области электроники.
Я что-то не догоняю или использование ШИМ в регулировке температуры фена по схеме Ильи c MOC3061 не возможно?
Просто на основе похожей схемы собрал диммер к ESP8266. В режиме реле работает отлично, а вот диммировать лампу накаливания не хочет (хотя замерял сопротивление через BTA16 изменяется от 5кОм и выше). Или MOC3061 с его детектором перехода через 0 тут ни при чем и я просто сделал что-то не так?
По поводу БП - можно взять такой http://www.aliexpress.com/item/New-Arrival-AC-Universal-100V-240V-for-DC-24V-4A-96W-Power-Supply-Charger-Converter-Adapter/32281525290.html
Тест на нем проводил - последовательно 2 лампы 12В 100Вт. Зажглись, ток выдал в районе 3,96А, в защиту не ушел, но хорошо гудел. Для паяльника должен подойти (для чего я собственно и заказывал).
Второй вопрос. Ардуины на борту имеют стабилизатор, на моей Мини Про LG50 - 500ма, до 12В. Вместе например с КРЕН 9В можно распределить тепло и уменьшить количество радиаторов. Токи вроде небольшие.
БП симпатичный и по деньгам вполне неплохо. Если он держит заявленные характеристики, то это как раз то, что нужно. Даже если будет срабатывать защита при холодном включении, теперь есть ШИМ-разогрев, который купирует эту проблему.
Насчет набортного регулятора ардуины -- использовать его по предложенной вами схеме проблематично. Помимо самого ардуины есть еще остальная схема, которая так же расчитана на питание от 5 вольт. Если туда подать 9 вольт, то это напряжение через светодиоды индикатора окажется на ногах ардуины и даже если не сожжет сразу, то начнет "поднимать" его, т.к. выходы внутри атмеги через защитные диоды соеденины с шиной +5v.
Насчет разогрева линейного регулятора (7805) хочу заметить, что несмотря на то, что греется он весьма ощутимо, температура прибора не выходит за рамки допустимых эксплуатационных пределов. Монтаж с использованием платы в качестве радиатора в данном случае допускает и большую тепловую нагрузку. Если не смотря на это кому-то хочется, чтобы вообще ничего не грелось, то нет никаих проблем в дырки от 7805 запаять провода с внешнего импульсного преобразователя. Так популярная понижайка на lm2596
вписывается сюда без каких бы то нибыло вопросов.
Я что-то не догоняю или использование ШИМ в регулировке температуры фена по схеме Ильи c MOC3061 не возможно?
Он включается только при переходе волны через ноль и всякий шим в другое время ему по барабану.
А как ФАКТИЧЕСКИ, не отображаемую на индикаторе, увеличить температуру жала?
Если честно, не понял вопроса.
По стабилизатору на борту я имел в виду, что даем 9В (можно даже 12В) на порт Vin или RAW (в зависимости от модели Ардуино), а с VCC отй же Ардуины получаем те же стабилизированные 5В до 500ма. Не знаю, как по току дисплей, но ток делителя напряжения примерно 2ма, регулятора еще меньше.
Но со step-down конвертером конечно же будет лучше. Только его еще заказать и дождаться нужно.
Мне интересный вопрос - не думали над защитой от зависания Ардуины при открытом полевике? Например, глобальный сброс при достижении критического сопротивления термистора.
Кстати, вспомнил еще один вопрос - зачем использовать опорный источник напряжения, если можно измерить фактическое напряжение приходящих 5В?
а с VCC отй же Ардуины получаем те же стабилизированные 5В до 500ма. Не знаю, как по току дисплей, но ток делителя напряжения примерно 2ма, регулятора еще меньше.
Ток через дисплей в пике составляет 7сегментов * 20ма = 140ма. Сам ардуино кушает 30-40ма. Добавим потребление прочих элементов схемы и в сумме получится где-то 200ма. Ток кажется вполне приемлемым. Но это только до того, как начнем считать мощность выделяемую в тепло на линейном стабилизаторе ардуины. А она будет выглядеть так: P= (Vin - Vout) * Iout. Для наших цифр это получится (12-5) * 0.2 = 1.4W, что является трижды запредельной величиной для того типа корпуса, в котором регулятор распаян на ардуине. Регулятору в таких условиях скорее всего захочется выпаяться (с этим у него проблем не возникнет) и убежать. :)
По хорошему, надо дописать использование аппаратного ватчдога ардуины в скетче. Только это будет не защита от неконтролируемого нагрева паяльника, а просто от зависания ардуины. Но тут есть подводные грабли, т.к. разработчики ардуины сделали все возможное, чтобы сделать использование ватчдога максимально сложным. Чтобы быстро выпустить рабочую версию скетча, от многих задумок, которые там должны, по-хорошему, присуствовать, мне пришлось, как минимум на время, отказаться.
Использование аппаратной защиты тянет за собой усложнение схемы и вызывает лишние сложности с повторением, особенно начинающими. По своему опыту эксплуатации различных самодельных паялок я знаю, что неконтролируемый разогрев паяльника ситуация довольно редкая. У меня это случалось только во время разработки и исключительно из-за собственной невнимательности. Риск того, что правильно собранная схема при подаче на нее рекомендованных напряжений самопроизвольно выйдет из строя не очень велик, т.ч. взвесив плюсы и минусы, от реализации аппаратной защиты я решил отказаться.
Если кому-то захочется повышенной надежности, то можно добавить в схему компаратор с порогом 1.2в и подключить его параллельно входу АЦП ардуины. На выходе компаратора будет формироваться аварийный сигнал в случае, если нагрев паяльника превысил допустимый диапазон.
В этом случае мы поимеем сразу несколько минусов по сравнению с нынешней схемой. Имеются достаточно значимые основания, чтобы так не делать, но чтобы еще больше не загромождать объяснение, просто встаньте осциллографом на шину +5в и посмотрите, что на ней твориться во время работы схемы. Если это употребить в качестве опорного напряжения, то о точности удержания температуры лучше 10-20 градусов можно даже и не заикаться.
Попробую объяснит - это про температуру. У меня по индикатору температура не устанавливается выше 439 градусов. По моим ощущениям (возможно ошибочным) это не соответствует действительности - температура на жале паяльника ниже. Калибровку по вашей методике делал - не сильно помогло. Можно ли поправить код таким образом что бы поднять температуру? Т.е. по индикатору предположим 300, а на жале - 350.
По переходу паяльника в "сон". Как то странно это происходит. На максимальной температуре паяльник лежит на подставке несколько десятка два минут - в "сон" не переключается, начал пользоваться (паять) плату - через полминуты запищал сигнал начала перехода в "сон" Может лучше режим "сон" назначить на кнопку? Нажал - паяльник уснул, через несколько минут (предположим минут 10-15) нагрев вообще выключился.
Мой совет, сначала все-таки установите сколь нибудь более достоверно, что ошибка индикации температуры имеет место. Я бы вот на глаз вряд ли смог различать температуры пяльника 440 и 380 градусов, скажем. И что вы, если не секрет, паяете при такой температуре жала? Я, например, уже не помню, когда последний раз что-то паял с температурой больше 320 градусов.
Если вам непременно хочется, чтобы паяльник грел сильнее, уменьшите значение
ADC_CALIBRATION_DATA_HIGH
Режим сна задуман, как средство против забывчивости. Оставлять паяльник включенным на долгое время все-таки не лучшая идея. Если в сон уходить только по кнопке, то велик шанс получить ситуацию, когда и на кнопку забудешь нажать, а паяльник будет сутки барабанить, дожигая жало.
Достаточно ли будет данного транзистора для управления питанием паяльника?
Достаточно ли будет данного транзистора для управления питанием паяльника?
не могу прочитать что на нем написано.
CEP603AL
CEP603AL
напряжение исток сток 30В. желательно с запасом ставить. Но работать будет. как долго не могу сказать. по остальным параметрам вопросов нет.
Подскажите правильно ли будет подключить корпус паяльника на общий минус и потом уже через конденсатор к общему минусу подключить заземляющий контур?
Что такое "заземляющий контур" ?
Подскажите правильно ли будет подключить корпус паяльника на общий минус и потом уже через конденсатор к общему минусу подключить заземляющий контур?
Что такое заземление?
это защита от поражения электрическим током человека.
Что подключается к заземлению?
Все нетоковедущие части электроустановки, которые могут оказаться под напряжением.
Из этого следует, что к заземлению нужно подключать все металлические части корпуса, которые могут оказаться под напряжением. конденсатор на землю, это не заземление.