Editor Version ×
recommended

Pro Edition

free

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

Std Edition

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

Completed

PRO MakerLab Electric height-adjustable desk

Electric height-adjustable desk

Project tags

License

BSD License

License: BSD License

Mode:

Mode

Editors' pick

Editors' pick

  • 16
  • 0
  • 0
Update time: 2024-11-06 02:46:13
Creation time: 2024-11-05 02:33:37
Description

Description

Project Description

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).

Main control part: ESP32 is used as the main control chip. The reasons for choosing it are as follows:

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

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.

 

Project Related Functions

Prompt:

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;

 

Project Properties

This project is made public for the first time and is my original project. The project has not won any awards in other competitions.

 

Project Progress

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.

 

Design Principles

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.

Get network time and alarm clock: When the table is powered on, ESP32 will automatically connect to the home WIFI and get the network time, which is displayed on the OLED. You can set the time required by pressing the corresponding alarm clock timer button. At the same time, the OLED will display the timed time, by reading the network time and comparing the time with the timed time. If equal, turn on the buzzer.

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.

 

Software Description

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);
}
 

Physical Display

Tips: Actual pictures of the work, you can add descriptions to the pictures.

paXnnQTIldRM6bDqbgGtdyPJhtgJwf1jXC7epMj0.jpeg

JyGiQV4c2Cz6aqtoa1GNbboxMWM9HR4BX6EhngXk.png

eSMdrZ9UggQLZHo1tO6V7q21MdZHlsvoYpEOvR6l.png

HgOjcDAlw0UZzd9jcRbvbiyW5heq8Mve8V71SOxl.png

The control panel is detachable and foldable.

PKSguTGWTg7wqAMeZKAcHITGXgfDMEKWuqbfMDWy.jpeg

URSicuMCN0gqNyFkvpXFivdm52ZVBZ5StSotwcHQ.png

5w3Uul1QU6VoZUYAVFn56U7F5fxkBOrWAOA8FECF.png

 

Design Considerations

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)

k2fMaJhw4x5nO9GYI8MU49hMTazWFC33n9NYt5kE.png

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.

b7VK2TjYtSxsgKAMB7DX48WXkcXcaDTxF3dZdhgA.png

In the fast charging circuit, the capacitors marked by arrows can be modified as needed.

 

Other

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

Design Drawing

Design Drawing

schematic diagram
1 /
PCB
1 /
The preview image was not generated, please save it again in the editor.
Empty
Project Members

Project Members

Target complaint
Related Projects
Change a batch
Loading...

Comment

Add to album ×

Loading...

reminder ×

Do you need to add this project to the album?

服务时间

周一至周五 9:00~18:00
  • 0755 - 2382 4495
  • 153 6159 2675

服务时间

周一至周五 9:00~18:00
  • 立创EDA微信号

    easyeda

  • QQ交流群

    664186054

  • 立创EDA公众号

    lceda-cn