I designed and made the stc white light by myself, with the schematic diagram, perforated board wiring diagram and source code attached.
Only simple temperature control is implemented. Short press the encoder to quickly set the temperature to 300℃, double click the encoder to quickly set it to 10℃ (equivalent to short sleep)
The code comments are very detailed and suitable for beginners to learn.
The microcontroller source program is as follows:
/**
A sky full of stars Written by CZS
*/
#include <STC15.h>
#include #include sbit t12 = P3 ^ 7; //T12 control sbit encoderb = P1 ^ 0; // encoder b pin sbit encodera = P1 ^ 1; // encoder pin a sbit encoderd = P1 ^ 2; // encoder key d pin sbit DIO = P3 ^ 3; // TM1650 digital tube driver sda pin sbit CLK = P3 ^ 2; // TM1650 digital tube driver scl pin sbit DO = P5 ^ 5; //DS18B20 data pin unsigned long VREF = 2390; // Use a multimeter to measure the true value of the reference voltage, in mv bit lastb = 0; bit lasta = 0; unsigned short push_last_time = 0; //Record the time the encoder button is pressed, short press and long press unsigned long t12_voltage; // Calculate t12 thermocouple voltage unsigned long system_voltage; // Calculate the microcontroller supply voltage unsigned long input_voltage; // Calculate the input voltage of the entire board (12~24V) //PID control algorithm #define KP 1.2f // proportional coefficient #define KI 0.2f // Integral coefficient #define KD 0.1f // differential coefficient #define MAX_UK 400.0f // The maximum control amount allowed by the system, here expressed as the number of heatings, 400 0.5ms heating cycles, and the longest continuous heating time is 200ms int ek = 0, ek_1 = 0, ek_2 = 0; // Record three consecutive deviation values (set value - actual measured value) float uk_1 = 0.0f, uk = 0.0f; // Record the currently calculated PID adjustment value and the last calculated PID adjustment value long integralSum = 0; // Cumulative integral term of position PID algorithm // Define a digital tube segment code table, 0~F unsigned char CODE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7C, 0X39, 0X5E, 0X79, 0X71}; unsigned int t12SetTemperature = 10; // Record the current set temperature unsigned int t12ActualTemperature = 0; // Save the current actual temperature of T12 bit isChangeTemperature = 0; // Mark whether the set temperature has been changed unsigned int setTempShowTime = 0; // Record the duration of displaying the set temperature unsigned int need_heat_time = 0; // Duration of heating required unsigned int heat_time_count = 0; //Current heating time unsigned int actualTempShowTime = 250; //Set the display time of the current temperature to avoid the digital tube jumping due to too fast temperature collection /*Delay function, automatically generated by STC-ISP, more accurate*/ void Delay_ms(unsigned int k) //@12.000MHz { unsigned char i, j; for (; k > 0; k--) { i = 12; j = 169; do { while (--j) ; } while (--i); } } void Delay_us(unsigned int i) { for (; i > 0; i--) { _nop_(); _nop_(); _nop_(); _nop_(); } } // Initialize each IO port void initIO() { //Configure the input mode of each port, M1M0: 00 normal, 01 push-pull, 10 high impedance input, 11 open drain /* The following lists the ports that need to be configured, and other ports can remain default t12 = P3^7; //T12 controls push-pull output mode ADC3: System input voltage detection P1^3 input mode ADC4: T12 thermocouple voltage detection P1^4 input mode ADC5: 2.5V reference voltage input P1^5 Input mode */ //P1M0 |= 0x00; //0000 0000 P1M1 |= 0x38; //0011 1000 P3M0 = 0x80; //1000 0000 P3M1 = 0x00; //0000 0000 } /*Initialize ADC*/ void initADC(void) { /* Enable the analog input function of the corresponding ADC port (corresponding position 1) ADC3: System input voltage detection P1^3 ADC4: T12 thermocouple voltage detection P1^4 ADC5: 2.5V reference voltage input P1^5 */ P1ASF = 0x38; //0011 1000 ADC_RES = 0; // Clear result register ADC_RESL = 0; /* ADC Control Register ADC_POWER | SPEED1 | SPEED0 | ADC_FLAG | ADC_START | CHS2 | CHS1 | CHS0 */ // When initializing here, you can turn on the power and set the conversion speed ADC_CONTR = 0x80; // 1000 0000 Delay_ms(5); // Delay and wait for a while after power on } // Turn off the ADC power supply and enable it when entering idle (sleep) mode to reduce power consumption void closeADC(void) { /* ADC Control Register ADC_POWER | SPEED1 | SPEED0 | ADC_FLAG | ADC_START | CHS2 | CHS1 | CHS0 */ ADC_CONTR = 0x00; } // Direct insertion sort void insertionSort(unsigned int A[], unsigned int n) { unsigned int i, j; for (i = 1; i < n; i++) { for (j = i; j > 0; j--) { if (A[j] < A[j - 1]) { // Do not use a third variable to swap two numbers, using XOR operation is fast A[j - 1] ^= A[j]; A[j] ^= A[j - 1]; A[j - 1] ^= A[j]; } } } } #define ADC_FLAG 0x10 // ADC conversion completed flag #define ADC_START 0x08 //ADC starts setting // Get the conversion value of an ADC channel // To improve the accuracy of the results, measure 5 times each time, remove the highest value and the lowest value, and finally take the average of the middle 3 and return it unsigned int getADCResult(unsigned int channel) { unsigned int res[5], i, result = 0; for (i = 0; i < 5; i++) { /* ADC Control Register ADC_POWER | SPEED1 | SPEED0 | ADC_FLAG | ADC_START | CHS2 | CHS1 | CHS0 */ ADC_CONTR = (0x80 | channel | ADC_START); // Select the channel to be read and start the conversion Delay_us(1); while (!(ADC_CONTR & ADC_FLAG)) ; //Wait for ADC conversion to complete res[i] = ((ADC_RES << 2) | (ADC_RESL & 0x03)); // Calculate the original result of the conversion ADC_RES = 0x00; ADC_RESL = 0x00; // Clear result register } // Sort the results insertionSort(res, 5); // Remove the highest value, remove the lowest value, and find the average of the remaining three result = (res[1] + res[2] + res[3]) / 3; return result; } /*The following are functions for calculating various voltages. The units of the returned results are all mv*/ // Calculation formula (mv) output_voltage = (TL431 reference voltage value measured by VREF multimeter (mv) * ADC value of the channel to be measured / ADC value of TL431 reference channel) // Calculate and obtain the voltage of T12 void getT12Voltage(void) { t12_voltage = (VREF * getADCResult(4) / getADCResult(5)); //Calculate t12 voltage, unit: mV } // Calculate and obtain the power supply voltage of the microcontroller void getSystemVoltage(void) { system_voltage = (VREF * 1024 / getADCResult(5)); //Calculate the power supply voltage of the MCU, in mV; } // Calculate the input power supply voltage void getInputVoltage(void) { input_voltage = (VREF * getADCResult(3) / getADCResult(5) * 11); // Calculate the voltage at the lower voltage divider resistor point and multiply it by the voltage divider ratio to get the actual input voltage } /* Calculate T12 thermocouple temperature*/ void getT12Temperature(void) { float x = 0.0f; t12 = 0; //When measuring temperature, turn off the soldering iron Delay_us(10); // Wait for a while, and measure the temperature more accurately after the capacitor is fully discharged getT12Voltage(); // Update T12 thermocouple voltage //T12 actual temperature = (ADC voltage (mV) - offset voltage (mV)) / op amp gain * thermocouple graduation value (℃/mV) + room temperature (℃) //t12Temp = 1.0f*getT12Voltage() / 231.0f * 54.0f + 23.0f; // The interpolation function calculates the T12 temperature. The above calculation is not accurate enough. I measured the relationship between the t12 temperature and the thermocouple electromotive force and used the formula fitted by matlab x = 1.0f * t12_voltage / 231.0f; x = -0.9f * x * x + 48.0f * x + 22.0f; t12ActualTemperature = (unsigned int)x; } /* // Incremental PID control algorithm. This algorithm has poor effect on temperature control. It took a long time to adjust the parameters, but it is not very ideal. // Input the set temperature and current temperature // Return the current heating time void incrementalPID(unsigned int setTemperature, unsigned int actualTemperature) { float delta_uk = 0.0f; // used to calculate PID increment value uk_1 = uk; // Record the last calculated PID adjustment value ek_2 = ek_1; // Record the deviation value calculated last time ek_1 = ek; // Record the deviation value calculated last time ek = setTemperature - actualTemperature; // Calculate the current deviation value if (ek < 0) { // If the actual temperature is higher than the set temperature, heating will not be performed need_heat_time = 0; return; } if (abs(ek) > 100) { // If the temperature difference is greater than 100°C, the system will be dynamically accelerated. Regardless of whether the proportional term is positive or negative, it will be a positive number. delta_uk = KP * abs(ek - ek_1) + KI * ek + KD * (ek - 2 * ek_1 + ek_2); // Calculate PID increment value } else { // When approaching the target temperature, perform normal adjustment delta_uk = KP * (ek - ek_1) + KI * ek + KD * (ek - 2 * ek_1 + ek_2); // Calculate PID increment value } uk = uk_1 + delta_uk; // Calculate the current PWM value that should be output // Determine whether it exceeds the boundary range of the system control quantity. If it exceeds, assign the value to the boundary if (uk < 1e-9) { uk = 0.0f; } if (uk > MAX_UK) { uk = MAX_UK; } need_heat_time = (unsigned int)uk; } */ // Position PID control algorithm, this control algorithm runs ideally void positionalPID(unsigned int setTemperature, unsigned int actualTemperature) { ek_1 = ek; // Record the deviation value calculated last time ek = setTemperature - actualTemperature; // Calculate the current deviation value
Previous article:Assembly language program debugging of LED light controller based on C8051F310 single chip microcomputer
Next article:51 single chip simple waveform generator (sine wave, sawtooth wave, triangle wave)
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- ASML predicts that its revenue in 2030 will exceed 457 billion yuan! Gross profit margin 56-60%
- Detailed explanation of intelligent car body perception system
- How to solve the problem that the servo drive is not enabled
- Why does the servo drive not power on?
- What point should I connect to when the servo is turned on?
- How to turn on the internal enable of Panasonic servo drive?
- What is the rigidity setting of Panasonic servo drive?
- How to change the inertia ratio of Panasonic servo drive
- What is the inertia ratio of the servo motor?
- Is it better for the motor to have a large or small moment of inertia?
- Show off the Sony headphones I got from EEWORLD
- Single tube amplifier
- TMS320F28335 SVPWM source program
- 【RPi PICO】CircuitPython Firmware
- msp430f5529 uart pwm adc
- [Help] In the design of lithium battery power modules, why is every 1V of lithium battery voltage very valuable?
- [DIY Bing Dun Dun] + Limited Edition Homemade Dun Dun is here
- EEWORLD University Hall----Live Replay: Unlocking New Possibilities of TI Sitara AM2x MCU in Motor Drive
- 02.USART routines and tests
- How to create and call schematic templates in AD?