© 2024 EasyEDA Some rights reserved ISO/IEC
Brand new interactions and interfaces
Smooth support for design sizes of over 3W
devices or 10W pads
More rigorous design constraints, more
standardized processes
For enterprises, more professional users
Easy to use and quick to get started
The process supports design scales of 300
devices or 1000 pads
Supports simple circuit simulation
For students, teachers, creators
PRO Electric height-adjustable desk
Mode:
It is divided into structural parts: This time I am selling a second-hand Changteng lifting table frame CTHT3-F4200 dual motor 3-section table frame through Xianyu. (Official reply: The noise is about 42 decibels, the maximum load-bearing capacity is 120KG, and the height adjustment range is 600 -1250mm).
1. Enough IO ports (I need almost 12, so based on this alone, it is more appropriate to use ESP32).
2. Enough interrupts (because I need to detect the Hall of the motor, interrupts are particularly important, and each IO port of the ESP32 can be used as an independent interrupt, which is very convenient).
3. Need to have I2C pins (need to control OLED).
4. A large enough EEPROM is needed to save the power-off height information.
5. Equipped with WIFI function to facilitate later IoT planning.
Motor control part: This time, BTS7960 (7970 is also acceptable in actual testing) motor driver chip is used. Its biggest feature is that it can output a maximum current of 27V43A. It is completely sufficient for the motor that drives the lifting table. At the same time, it also needs a larger heat sink to dissipate the heat of the chip, which results in a larger size, but it is completely sufficient for the space under the table.
Main power supply part: After disassembling the motor, I found that the single motor is an 18V, 4.3A worm motor. Through testing, I found that the normal rotation current of the motor is about 2A. Considering the load-bearing problem, I chose an AD-DC power supply with an output of 15V10A. module. About 15 yuan or so.
Display part: A 0.96-inch OLED is used as the height display screen to display time, alarm settings, height, etc.
Fast charging part: Using IP5306 fast charging chip, the maximum output power can reach 45W.
Open source agreement description.
This is the "Berkeley Software Distribution" license, which is an agreement that gives users a lot of freedom. Basically, it can be considered as being able to "do whatever they want".
You can freely use and modify the source project, and you can also re-release the modified original project as open source or proprietary, but the following conditions need to be met:
a. If the re-released product contains the source project, the original BSD protocol must be included in the project;
b. If only a binary class library or software is redistributed, the BSD protocol in the original code needs to be included in the documentation and copyright statement of the class library or software;
c. Do not use the name of the open source author or organization or the name of the original product for marketing purposes.
1.Maximum lifting height: 120CM, minimum height: 60CM;
2.Desktop area: 120cmX60cm;
3.Maximum load-bearing: 50KG, and the height cannot be rebounded;
4.Number of motors: 1-2;
5.Screen display: time, current table height;
6.USB fast charging, fast charging protocol is not limited;
7.Power-off memory can ensure that the table height is consistent after power-off and restart;
8.The noise agreement when the table is raised and lowered is below: 45DB-below;
9.Support alarm clock reminder;
This project is made public for the first time and is my original project. The project has not won any awards in other competitions.
July 1: The lifting table arrived for debugging, the size and installation position of each module were determined, and the modeling of the control panel shell began.
July 3: Manually weld the control board, write code, and test whether the performance of the lifting table meets the requirements.
July 10: The PCB schematic design includes (motor drive, control part, OLED screen display, button control, limit switch settings, USB fast charging settings) power-off memory and alarm clock in the final debugging part.
July 13: PCB diagram design, proofing.
July 13: Electronic components procurement.
July 20: PCB welding and debugging.
Note: I am afraid that there may be a time conflict and there is not enough debugging time. I will consider the power module comprehensively and may have to do it later. Please understand.
First of all, the hardware part is measured and the chip selection is made to determine the appropriate PCB size and chip type to ensure that the design requirements are met.
By dismantling the motor, each motor has two halls. When the magnetic ring of the motor rotates, because the magnetic ring is divided into S and N poles, the two halls will detect different values. For example, when the No. 1 hall detects a low level, and the No. 2 Hall detects a high level, it is judged that the motor is rotating clockwise, which also means that the desktop is rising. If No. 2 motor is low, it is judged that the motor is rotating counterclockwise and the table top is falling at the same time. So I set 5 keys, respectively, up, down, alarm clock hour timing setting, alarm clock minute timing setting, clear key.
When the rise button is pressed, ESP32 output two PWM control, two table leg motors rise, at the same time, due to the rotation of the motor, the Hall sensor detects the rotation, triggers the interruption and sends the read pulse to ESP32 and records it. When it rises to the required height, the current height is calculated by calling the function formula. It is displayed on the OLED and saved to EEPROM to prevent power loss. After repeated calculation and measurement, when the table is at the maximum height of 1200mm, the output pulse is 2569 pulses, that is to say, when the height reaches 1200mm, the motor stops rising.
When the drop button is pressed, the ESP32 output two PWM signal control, the two legs drop, when the height is detected greater than or equal to 0, it is already in the end, stop falling, the same reason, the pulse is 0 when the lowest height is dropped.
EEPROM part: When the up or down button is pressed, the current height will be stored in EEPROM; when the power is off, it will be saved in EEPROM; when the power is on again, it will directly read the last saved height. And in the height of the rise and fall of the height calculation, to prevent the current height value zero after the power outage.
Power supply part: By using the adjustable power supply of positive point atom for measurement, it is known that in the normal operation state (the adjustable power supply is set to 12V5A), the current of a single motor is about 2.5A. Since the motor parameter is 18V4.3A, considering the load bearing and starting current, AC-DC15V10A power supply module is selected this time.
I will analyze the program in detail. If you don’t understand, you can watch the video (Station B: Mr. Zhao’s PCB)
The library functions used in this project
#include
#include
#include
#include
#include
#include
#include
#include
#include
Pin definition for ESP32:
const int ENC_A = 22;//A Hall sensor
const int ENC_B = 23;//B Hall sensor
const int ENC_C = 34;
const int ENC_D = 35;
const int RPWM = 18;//RPWM Pin
const int LPWM = 19;//LPWM Pin
const int RPWM1 = 33;
const int LPWM1 = 32;
const int BuzzerPin = 21;//Buzzer
const int Button1 = 17;//Rise key
const int Button2 = 16;//Drop key
const int Button3 = 25;//The hour button
const int Button4 = 26;//Key in minutes
const int Button5 = 27;//Cancel key
Here's the wifi part:
#define WIFI_SSID "OnePlus 9 Pro"
#define WIFI_PASSWORD "12345678"
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
//The time of the current area can be accurately obtained through "pool.ntp.org" and displayed on the OLED
Major variable:
int alarmHour = 0; //Alarm clock hour
int alarmMinute = 0; //Alarm minute
bool alarmOn = false; //Alarm status
volatile int contador = 0; //Number of pulses output by Hall 1
volatile bool direction = false; //false is up and true is down
volatile int contador1 = 0; //Number of pulses output by Hall 2
volatile bool direction1 = false; //false is up and true is down
const int MIN_HEIGHT = 0; //minimum altitude
const int MAX_HEIGHT = 60;//maximum height
const int MAX_PULSES = 2569; //Encoder pulse maximum
int currentHeight = 0; //Current height
int currentHeight1 = 0;
bool alarmEnabled = false; //Whether the alarm is on or not
bool Button1State = HIGH; //Key press status
bool Button2State = HIGH;
bool Button3State = HIGH;
bool Button4State = HIGH;
bool Button5State = HIGH;
A more trashy table pattern:
static const uint8_t image_data_Saraarray[1024] = { //Animated OLGO
0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00,
0x00,0x03,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFE,0x00,0x00,0x00,0x00,
0x00,0x3F,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x01,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,
0x1F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,
0x7F,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x00,
0x0F,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,
0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,
0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x4F,0xFF,0xFF,0xFF,0xFF,0xFE,
0x00,0x00,0x63,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x66,0x7F,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x67,0x3F,0xFF,0xFF,0xFF,0xF0,
0x00,0x00,0x67,0x0F,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x67,0x03,0xFF,0xFF,0xFF,0x00,
0x00,0x00,0x67,0x01,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x67,0x00,0x3F,0xFF,0xF0,0x00,
0x00,0x00,0x67,0x00,0x1F,0xFF,0xE0,0x00,0x00,0x00,0x67,0x00,0x07,0xFF,0x80,0x00,
0x00,0x00,0x67,0x00,0x01,0xFC,0x00,0x00,0x00,0x00,0x67,0x00,0x00,0x79,0x00,0x00,
0x00,0x00,0x67,0x78,0x00,0x57,0x00,0x00,0x00,0x00,0x67,0xFE,0x00,0x67,0x00,0x00,
0x00,0x00,0x67,0xFE,0x00,0x77,0x00,0x00,0x00,0x00,0x67,0xF0,0x00,0x77,0x00,0x00,
0x00,0x00,0x67,0xE0,0x00,0x77,0x00,0x00,0x00,0x00,0xE7,0xC0,0x00,0x77,0x00,0x00,
0x00,0x01,0xE7,0x00,0x00,0x77,0x00,0x00,0x00,0x07,0xEC,0x00,0x00,0x77,0x00,0x00,
0x00,0x1F,0xF8,0x00,0x00,0x77,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x77,0x00,0x00,
0x00,0x7F,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x77,0x00,0x00,
0x00,0x04,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x77,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x77,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0xFE,0x00,
0x00,0x00,0x00,0x00,0x00,0x77,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0xF8,0x00,
0x00,0x00,0x00,0x00,0x00,0x77,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0xC0,0x00,
0x00,0x00,0x00,0x00,0x00,0xF7,0x80,0x00,0x00,0x00,0x00,0x00,0x03,0xF6,0x00,0x00,
0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,
0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
Next is the setup() function:
Initializing serial port: Serial.begin(115200);//Initializing serial port
Initialize EEPROM: EEPROM.begin(EEPROM_SIZE);
Initialize OLED: Wire.begin(OLED_SDA, OLED_SCL);
IO pin initialization:
pinMode(ENC_A, INPUT); //Hall pin initialization
pinMode(ENC_B, INPUT);
pinMode(ENC_C, INPUT);
pinMode(ENC_D, INPUT);
pinMode(RPWM, OUTPUT); //Motor drive part initialization
pinMode(LPWM, OUTPUT);
pinMode(RPWM1, OUTPUT);
pinMode(LPWM1, OUTPUT);
pinMode(BuzzerPin, OUTPUT);
pinMode(Button1, INPUT_PULLUP); //Key 1 is the input pull-up mode
pinMode(Button2, INPUT_PULLUP); //Key 2 is the input pull-up mode
pinMode(Button3, INPUT_PULLUP);
pinMode(Button4, INPUT_PULLUP);
pinMode(Button5, INPUT_PULLUP);
Set interrupt detection Hall pulse:
attachInterrupt(digitalPinToInterrupt(ENC_A), interrupcion, RISING);//Rising edge trigger
attachInterrupt(digitalPinToInterrupt(ENC_B), interrupcion, RISING);
attachInterrupt(digitalPinToInterrupt(ENC_C), interrupcion1, RISING);//Rising edge trigger
attachInterrupt(digitalPinToInterrupt(ENC_D), interrupcion1, RISING);
Use this function to determine whether it is currently in a rising or falling state:
void interrupcion(){
int stateA = digitalRead(ENC_A);
int stateB = digitalRead(ENC_B);
if(stateA == HIGH && stateB == LOW){
contador++;
if(contador > MAX_PULSES){
contador = MAX_PULSES;
}
direction = true;//
}else if(stateA == LOW && stateB == HIGH){
contador--;
if(contador
contador = 0;
}
direction = false;
}
currentHeight = map(contador, 0 , MAX_PULSES, MIN_HEIGHT, MAX_HEIGHT);
}
Note: interrupcion1 is the same
Read the value saved by the EEPROM power off and assign the value to the current height
currentHeight = EEPROM.read(0);
currentHeight1 = EEPROM.read(1);
currentHeight = constrain(currentHeight, MIN_HEIGHT, MAX_HEIGHT);
currentHeight1 = constrain(currentHeight1, MIN_HEIGHT, MAX_HEIGHT);
updatwMotorPosition(); //When we power off the height is 30cm then, when the power back on the initial value should be 30cm
void updatwMotorPosition() {
int pulses = map(currentHeight, MIN_HEIGHT, MAX_HEIGHT, 0, MAX_PULSES);
contador = pulses;
int pulses1 = map(currentHeight1, MIN_HEIGHT, MAX_HEIGHT, 0, MAX_PULSES);
contador1 = pulses1;
}
Next is the IOOP function:
//OLED displays the current time
display.clearDisplay(); //Clear display image
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(20, 13);
display.print("T:");
display.println(timeClient.getFormattedTime()); //
//OLED display timing time
display.setCursor(20, 30);
display.print("DING:"); //"DING "
display.print(alarmHour); //Hour
display.print(":");
display.println(alarmMinute);//Minute
checkAlarmTrigger(); //Start timer function
//Compares the current time with the set time, and triggers the buzzer if the time is equal
void checkAlarmTrigger(){
int currentHour = timeClient.getHours();
int currentMinute = timeClient.getMinutes();
if (alarmEnabled && currentHour == alarmHour && currentMinute == alarmMinute) {
digitalWrite(BuzzerPin, HIGH);
Serial.println("buzzer warning");
Serial.print("currentHour: ");
Serial.println(currentHour);
Serial.print("currentMinute: ");
Serial.println(currentMinute);
Serial.print("alarmHour: ");
Serial.println(alarmHour);
Serial.print("alarmMinute: ");
Serial.println(alarmMinute);
Serial.print("alarmEnabled: ");
Serial.println(alarmEnabled);
// You can add code here to display alarm information on the OLED
delay(500);
cancelAlarm(); // The alarm is automatically canceled when it rings
}
}
Next comes the key read section
Button1State = digitalRead(Button1); //Read the status of key 1
Button2State = digitalRead(Button2); //Read the status of key 2
Button3State = digitalRead(Button3);
Button4State = digitalRead(Button4);
Button5State = digitalRead(Button5);
if(Button1State == LOW && currentHeight1
if(!direction){
ShangSheng();
if(currentHeight >= MAX_HEIGHT){
ShangShengStup();
}
}
EEPROM.write(0, currentHeight);
EEPROM.write(1, currentHeight1);
EEPROM.commit();
}else{
ShangShengStup();
}
if(Button2State == LOW && currentHeight1 > MIN_HEIGHT){//If button 2 is pressed the table leg begins to fall
if(direction){
XiaJiang();
if(currentHeight 23) {
alarmHour = 0;
}
}
void incrementAlarmMinute() {//Set up minutes
alarmMinute++;
alarmEnabled = true;
if (alarmMinute > 59) {
alarmMinute = 0;
}
}
void cancelAlarm() {// Code to stop the buzzer
alarmEnabled = false;
alarmHour = 0; // Reset alarm clock hours
alarmMinute = 0; // Clear alarm clock minutes
// Code to stop the buzzer
digitalWrite(BuzzerPin, LOW);
}
Tips: Actual pictures of the work, you can add descriptions to the pictures.
The control panel is detachable and foldable.
Tip: Here are some precautions that need to be paid attention to in the production of the work (if not, you can leave it out)
The AMS1117 used in the circuit diagram, according to current judgment, will generate a lot of heat. The preliminary judgment is that the AMS117 I bought may have quality problems. Of course, it is recommended that you replace it with AS1117.
When actually burning the program, you need to first burn a program to clear the ESP32 and EEPROM to prevent the wrong height from being read.
In the fast charging circuit, the capacitors marked by arrows can be modified as needed.
Station B: Spark Project-Electric lift table hardware part_bilibili_bilibili
Station B: Electric lift table program_bilibili_bilibili
Demonstration video: The demonstration video can upload the attachment, the attachment can only long transfer 50M files, more than 50M files can be placed in other network disk or video website, just put the address link here
Project attachments: Works participating in the event must upload project-related program attachments to the open source platform or personal code storage cloud. The attachment can be uploaded up to 50M (please do not upload it in the LC workspace, there are restrictions)
Designed by zhaoyiyi1 (from OSHWHub)
Link:https://oshwhub.com/zhaoyiyi1/dian-dong-sheng-xiang-zhuo
Loading...
Do you need to add this project to the album?