본문 바로가기

ESP32

esp32 자동차 무선 제어

반응형

 

여기에서 코드, 회로도 및 3D 모델을 찾을 수 있습니다 "https://github.com/RED9030/ESP_NOW_RC_CONTROL" 이것은 프로토타입일 뿐이며 3D 모델은 골판지 또는 우리가 가지고 있는 다른 재료로 만들 수 있는 아이디어를 얻기 위한 것임을 상기시켜 드립니다. 

 

자료 Github 주소

 

https://github.com/RED9030/ESP_NOW_RC_CONTROL?fbclid=IwZXh0bgNhZW0CMTAAAR3Kc75zvwmgSl6V_SHb1D8N1Yssz6NkIkofY3kuOWYpj0rkNueRbXrtpUg_aem_RM3PQ0vuNHe8BUXwnYZz5A

 

 

송신부

 

 

TX_RC_ESPNOW_CARS_ESP8266

 

 

수신부

 

 

RX_RC_ESPNOW_CARS_ESP32

 

 

RX_RC_ESPNOW_CARS_ESP32

 

 

 

ESP32 Car RX Code

 

/*
  MODDER: @RED9030
*/
/*
  Title: ESPNOW ESP32 CAR RX
  Este sketch permite la recepción de los datos mediante la comunicación ESP-NOW
  Carro control remoto usando protocolo espNOW 2.4GHz, 4 motores tracción trasera/delantera y giros.
  
  HardWare: ESP32
*/

/*
 *****************************************************
 *    LIBRERIAS
 *****************************************************
*/
#include <esp_now.h>
#include <WiFi.h>

/*
 *****************************************************
 *    VARIABLES
 *****************************************************
*/
//Right motor
int enableRightMotor=15;    //Enable Motor B 
int rightMotorPin1=19;      //In 3
int rightMotorPin2=18;      //In 4
//Left motor
int enableLeftMotor=5;     //Enable Motor A
int leftMotorPin1=22;      //In 1
int leftMotorPin2=21;      //In 2

#define MAX_MOTOR_SPEED 200

const int PWMFreq = 1000;                   // 1 KHz 
const int PWMResolution = 8;                // Resolutions bits "8bits"
const int rightMotorPWMSpeedChannel = 4;    //PWM channel Right motor
const int leftMotorPWMSpeedChannel = 5;     //PWM channel Left motor

#define SIGNAL_TIMEOUT 1000  // This is signal timeout in milli seconds. We will reset the data if no signal
unsigned long lastRecvTime = 0;

struct PacketData
{
  byte xAxisValue;
  byte yAxisValue;
  byte switchPressed;
};
PacketData receiverData;

bool throttleAndSteeringMode = false;

//Lights
#define LDright 4  //Directional right
#define LDleft  2  //Directional Left
#define LStop   6  //Stop Light
#define LNight  7  //Diurn Light
#define Horn 34    //Horn

/*
 *****************************************************
 *    FUNCIONES
 *****************************************************
*/
// Callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) 
{
  if (len == 0)
  {
    return;
  }
  memcpy(&receiverData, incomingData, sizeof(receiverData));
  String inputData ;
  inputData = inputData + "values " + receiverData.xAxisValue + "  " + receiverData.yAxisValue + "  " + receiverData.switchPressed;
  Serial.println(inputData);
  if (receiverData.switchPressed == true)
  {
    if (throttleAndSteeringMode == false)
    {
      throttleAndSteeringMode = true;
    }
    else
    {
      throttleAndSteeringMode = false;
    }
  }

  if (throttleAndSteeringMode)
  {
    throttleAndSteeringMovements();
  }
  else
  {
    simpleMovements();
  }

  lastRecvTime = millis();   
}

//Simple motor movements
void simpleMovements()
{
  if (receiverData.yAxisValue <= 75)       //Move car Forward
  {
    rotateMotor(MAX_MOTOR_SPEED, MAX_MOTOR_SPEED);
    digitalWrite(LDright,LOW);
    digitalWrite(LDleft,LOW);
    digitalWrite(LStop,LOW);
  }
  else if (receiverData.yAxisValue >= 175)   //Move car Backward
  {
    rotateMotor(-MAX_MOTOR_SPEED, -MAX_MOTOR_SPEED);
    digitalWrite(LStop,HIGH);
    digitalWrite(LDright,LOW);
    digitalWrite(LDleft,LOW);
  }
  else if (receiverData.xAxisValue >= 175)  //Move car Right
  {
    rotateMotor(-MAX_MOTOR_SPEED, MAX_MOTOR_SPEED);
    digitalWrite(LStop,LOW);
    blinkingLed(LDright);
  }
  else if (receiverData.xAxisValue <= 75)   //Move car Left
  {
    rotateMotor(MAX_MOTOR_SPEED, -MAX_MOTOR_SPEED);
    digitalWrite(LStop,LOW);
    blinkingLed(LDleft);
  }
  else                                      //Stop the car
  {
    rotateMotor(0, 0);
    digitalWrite(LDright,LOW);
    digitalWrite(LDleft,LOW);
    digitalWrite(LStop,LOW);
    digitalWrite(LNight,LOW);
    
  }   
}

//Direction and aceleration Movements
void throttleAndSteeringMovements()
{
  int throttle = map( receiverData.yAxisValue, 254, 0, -255, 255);
  int steering = map( receiverData.xAxisValue, 0, 254, -255, 255);  
  int motorDirection = 1;
  
  if (throttle < 0)       //Move car backward
  {
    motorDirection = -1;    
  }

  int rightMotorSpeed, leftMotorSpeed;
  rightMotorSpeed =  abs(throttle) - steering;
  leftMotorSpeed =  abs(throttle) + steering;
  rightMotorSpeed = constrain(rightMotorSpeed, 0, 255);
  leftMotorSpeed = constrain(leftMotorSpeed, 0, 255);

  rotateMotor(rightMotorSpeed * motorDirection, leftMotorSpeed * motorDirection);
}

//Rotación del vehículo
void rotateMotor(int rightMotorSpeed, int leftMotorSpeed)
{
  if (rightMotorSpeed < 0)
  {
    digitalWrite(rightMotorPin1,LOW);
    digitalWrite(rightMotorPin2,HIGH);    
  }
  else if (rightMotorSpeed > 0)
  {
    digitalWrite(rightMotorPin1,HIGH);
    digitalWrite(rightMotorPin2,LOW);      
  }
  else
  {
    digitalWrite(rightMotorPin1,LOW);
    digitalWrite(rightMotorPin2,LOW);      
  }
  
  if (leftMotorSpeed < 0)
  {
    digitalWrite(leftMotorPin1,LOW);
    digitalWrite(leftMotorPin2,HIGH);    
  }
  else if (leftMotorSpeed > 0)
  {
    digitalWrite(leftMotorPin1,HIGH);
    digitalWrite(leftMotorPin2,LOW);      
  }
  else
  {
    digitalWrite(leftMotorPin1,LOW);
    digitalWrite(leftMotorPin2,LOW);      
  } 

  ledcWrite(rightMotorPWMSpeedChannel, abs(rightMotorSpeed));
  ledcWrite(leftMotorPWMSpeedChannel, abs(leftMotorSpeed));    
}

//Configuraciones de los pines
void setUpPinModes()
{
  //Right Motors
  pinMode(enableRightMotor,OUTPUT);
  pinMode(rightMotorPin1,OUTPUT);
  pinMode(rightMotorPin2,OUTPUT);
  //Left Motors  
  pinMode(enableLeftMotor,OUTPUT);
  pinMode(leftMotorPin1,OUTPUT);
  pinMode(leftMotorPin2,OUTPUT);
  //Lights & Horn
  pinMode(LDright,OUTPUT);
  pinMode(Left,OUTPUT);
  pinMode(LStop,OUTPUT);
  pinMode(LNight,OUTPUT);
  pinMode(Horn,OUTPUT);

  //Set up PWM for motor speed
  ledcSetup(rightMotorPWMSpeedChannel, PWMFreq, PWMResolution);
  ledcSetup(leftMotorPWMSpeedChannel, PWMFreq, PWMResolution);  
  ledcAttachPin(enableRightMotor, rightMotorPWMSpeedChannel);
  ledcAttachPin(enableLeftMotor, leftMotorPWMSpeedChannel); 
  
  rotateMotor(0, 0);
}

//Función para hacer brillar un led
blinkingLed(const int Pin)
{
    digitalWrite(Pin,HIGH);
    delay(500);
    digitalWrite(Pin,LOW);
    delay(500);
  }

/*
 *****************************************************
 *    INICIO
 *****************************************************
*/
void setup() 
{
  setUpPinModes();
  
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) 
  {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  esp_now_register_recv_cb(OnDataRecv);
}

/*
 *****************************************************
 *    REPETICIÓN
 *****************************************************
*/
void loop() 
{
  //Check Signal lost.
  unsigned long now = millis();
  if ( now - lastRecvTime > SIGNAL_TIMEOUT ) 
  {
    rotateMotor(0, 0);
  }
}

 

 

ESP32 Car TX Code

 

 

/*
  MODDER: @RED9030
*/
/*
  Title: ESPNOW ESP32 CAR TX
  Este sketch permite la transmición de dos datos mediante la comunicación ESP-NOW
  Carro control remoto usando protocolo espNOW, 4 motores tracción trasera/delantera y giros.

  HardWare: ESP32
*/

/*
 *****************************************************
 *    LIBRERIAS
 *****************************************************
*/
#include <esp_now.h>
#include <WiFi.h>

/*
 *****************************************************
 *    VARIABLES
 *****************************************************
*/
#define X_AXIS_PIN 32
#define Y_AXIS_PIN 33
#define SWITCH_PIN 25

// RECEIVER MAC Address
uint8_t receiverMacAddress[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};  //Here mac for Receptor (RX)

struct PacketData
{
  byte xAxisValue;
  byte yAxisValue;
  byte switchPressed;
};
PacketData data;

/*
 *****************************************************
 *    FUNCIONES
 *****************************************************
*/
//This function is used to map 0-4095 joystick value to 0-254. hence 127 is the center value which we send.
//It also adjust the deadband in joystick.
//Jotstick values range from 0-4095. But its center value is not always 2047. It is little different.
//So we need to add some deadband to center value. in our case 1800-2200. Any value in this deadband range is mapped to center 127.
int mapAndAdjustJoystickDeadBandValues(int value, bool reverse)
{
  if (value >= 2200)
  {
    value = map(value, 2200, 4095, 127, 254);
  }
  else if (value <= 1800)
  {
    value = map(value, 1800, 0, 127, 0);  
  }
  else
  {
    value = 127;
  }

  if (reverse)
  {
    value = 254 - value;
  }
  return value;
}

// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
{
  Serial.print("\r\nLast Packet Send Status:\t ");
  Serial.println(status);
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Message sent" : "Message failed");
}

/*
 *****************************************************
 *    INICIO
 *****************************************************
*/
void setup() 
{
  
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) 
  {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  else
  {
    Serial.println("Succes: Initialized ESP-NOW");
  }

  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  esp_now_peer_info_t peerInfo;
  memset(&peerInfo, 0, sizeof(esp_now_peer_info_t));
  memcpy(peerInfo.peer_addr, receiverMacAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK)
  {
    Serial.println("Failed to add peer");
    return;
  }
  else
  {
    Serial.println("Succes: Added peer");
  } 

  pinMode(SWITCH_PIN, INPUT_PULLUP);   
}

/*
 *****************************************************
 *    REPETICIÓN
 *****************************************************
*/ 
void loop() 
{
  data.xAxisValue = mapAndAdjustJoystickDeadBandValues(analogRead(X_AXIS_PIN), false);
  data.yAxisValue = mapAndAdjustJoystickDeadBandValues(analogRead(Y_AXIS_PIN), false);  
  data.switchPressed = false; 

  if (digitalRead(SWITCH_PIN) == LOW)
  {
    data.switchPressed = true;
  }
  
  esp_err_t result = esp_now_send(receiverMacAddress, (uint8_t *) &data, sizeof(data));
  if (result == ESP_OK) 
  {
    Serial.println("Sent with success");
  }
  else 
  {
    Serial.println("Error sending the data");
  }    
  
  if (data.switchPressed == true)
  {
    delay(500);
  }
  else
  {
    delay(50);
  }
}

 

 

 

ESP8266 Car RX Code

 

/*
  MODDER: @RED9030
*/
/*
  Title: ESPNOW ESP8266 CAR RX
  Este sketch permite la recepción de los datos mediante la comunicación ESP-NOW
  Carro control remoto usando protocolo espNOW 2.4GHz, 4 motores tracción trasera/delantera y giros.
  
  HardWare: ESP8266
*/
 
/*
  PINES: Luces D0,D7,D8 MOTOR_ENABLES ENA-D5 ENB-D6
*/

/*
 *****************************************************
 *    LIBRERIAS
 *****************************************************
*/
#include <espnow.h>
#include <ESP8266WiFi.h>

/*
 *****************************************************
 *    VARIABLES
 *****************************************************
*/
//Rear motor
int enableRightMotor=5; 
int rightMotorPin1=3;
int rightMotorPin2=4;
//Front motor
int enableLeftMotor=6;
int leftMotorPin1=1;
int leftMotorPin2=2;

#define MAX_MOTOR_SPEED 200

const int PWMFreq = 1000; /* 1 KHz */
const int PWMResolution = 8;
const int rightMotorPWMSpeedChannel = 4;
const int leftMotorPWMSpeedChannel = 5;

#define SIGNAL_TIMEOUT 1000  // Este es el tiempo de espera de la señal en milisegundos. Restableceremos los datos si no hay señal
unsigned long lastRecvTime = 0;

struct PacketData
{
  byte xAxisValue;
  byte yAxisValue;
  byte switchPressed;
};
PacketData receiverData;

bool throttleAndSteeringMode = false; //Habilita la Dirección y aceleración 

/*
 *****************************************************
 *    FUNCIONES
 *****************************************************
*/
// callback function that will be executed when data is received
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) 
{
  if (len == 0)
  {
    return;
  }
  memcpy(&receiverData, incomingData, sizeof(receiverData));
  String inputData ;
  inputData = inputData + "values " + receiverData.xAxisValue + "  " + receiverData.yAxisValue + "  " + receiverData.switchPressed;
  Serial.println(inputData);
  if (receiverData.switchPressed == true)
  {
    if (throttleAndSteeringMode == false)
    {
      throttleAndSteeringMode = true;
    }
    else
    {
      throttleAndSteeringMode = false;
    }
  }

  if (throttleAndSteeringMode)
  {
    throttleAndSteeringMovements();
  }
  else
  {
    simpleMovements();
  }

  lastRecvTime = millis();   
}

//Simple motor movements
void simpleMovements()
{
  if (receiverData.yAxisValue <= 75)       //Move car Forward
  {
    rotateMotor(MAX_MOTOR_SPEED, MAX_MOTOR_SPEED);
  }
  else if (receiverData.yAxisValue >= 175)   //Move car Backward
  {
    rotateMotor(-MAX_MOTOR_SPEED, -MAX_MOTOR_SPEED);
  }
  else if (receiverData.xAxisValue >= 175)  //Move car Right
  {
    rotateMotor(-MAX_MOTOR_SPEED, MAX_MOTOR_SPEED);
  }
  else if (receiverData.xAxisValue <= 75)   //Move car Left
  {
    rotateMotor(MAX_MOTOR_SPEED, -MAX_MOTOR_SPEED);
  }
  else                                      //Stop the car
  {
    rotateMotor(0, 0);
  }   
}

//Direction and aceleration Movements
void throttleAndSteeringMovements()
{
  int throttle = map( receiverData.yAxisValue, 254, 0, -255, 255);
  int steering = map( receiverData.xAxisValue, 0, 254, -255, 255);  
  int motorDirection = 1;
  
  if (throttle < 0)       //Move car backward
  {
    motorDirection = -1;    
  }

  int rightMotorSpeed, leftMotorSpeed;
  rightMotorSpeed =  abs(throttle) - steering;
  leftMotorSpeed =  abs(throttle) + steering;
  rightMotorSpeed = constrain(rightMotorSpeed, 0, 255);
  leftMotorSpeed = constrain(leftMotorSpeed, 0, 255);

  rotateMotor(rightMotorSpeed * motorDirection, leftMotorSpeed * motorDirection);
}


//Rotación del vehículo
void rotateMotor(int rightMotorSpeed, int leftMotorSpeed)
{
  if (rightMotorSpeed < 0)
  {
    digitalWrite(rightMotorPin1,LOW);
    digitalWrite(rightMotorPin2,HIGH);    
  }
  else if (rightMotorSpeed > 0)
  {
    digitalWrite(rightMotorPin1,HIGH);
    digitalWrite(rightMotorPin2,LOW);      
  }
  else
  {
    digitalWrite(rightMotorPin1,LOW);
    digitalWrite(rightMotorPin2,LOW);      
  }
  
  if (leftMotorSpeed < 0)
  {
    digitalWrite(leftMotorPin1,LOW);
    digitalWrite(leftMotorPin2,HIGH);    
  }
  else if (leftMotorSpeed > 0)
  {
    digitalWrite(leftMotorPin1,HIGH);
    digitalWrite(leftMotorPin2,LOW);      
  }
  else
  {
    digitalWrite(leftMotorPin1,LOW);
    digitalWrite(leftMotorPin2,LOW);      
  } 

  analogWrite(rightMotorPWMSpeedChannel,abs(rightMotorSpeed));
  analogWrite(leftMotorPWMSpeedChannel,abs(leftMotorSpeed));    
}

void setUpPinModes()
{
  pinMode(enableRightMotor,OUTPUT);
  pinMode(rightMotorPin1,OUTPUT);
  pinMode(rightMotorPin2,OUTPUT);
  
  pinMode(enableLeftMotor,OUTPUT);
  pinMode(leftMotorPin1,OUTPUT);
  pinMode(leftMotorPin2,OUTPUT);

 /*
 //No necessary for esp8266
  //Set up PWM for motor speed
  ledcSetup(rightMotorPWMSpeedChannel, PWMFreq, PWMResolution);
  ledcSetup(leftMotorPWMSpeedChannel, PWMFreq, PWMResolution);  
  ledcAttachPin(enableRightMotor, rightMotorPWMSpeedChannel);
  ledcAttachPin(enableLeftMotor, leftMotorPWMSpeedChannel); 
 */
  rotateMotor(0, 0);
}

/*
 *****************************************************
 *    INICIO
 *****************************************************
*/
void setup() 
{
  setUpPinModes();
  
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != 0) 
  {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  //esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(OnDataRecv);
}

/*
 *****************************************************
 *    REPETICIÓN
 *****************************************************
*/
void loop() 
{
  //Check Signal lost.
  unsigned long now = millis();
  if ( now - lastRecvTime > SIGNAL_TIMEOUT ) 
  {
    rotateMotor(0, 0);
  }
}

 

 

ESP8266 Car TX Code

 

 

/*
  MODDER: @RED9030
*/
/*
  Title: ESPNOW ESP8266 CAR TX
  Este sketch permite la transmición de dos datos mediante la comunicación ESP-NOW
  Carro control remoto usando protocolo espNOW, 4 motores tracción trasera/delantera y giros.

  HardWare: ESP8266
*/

/*
 *****************************************************
 *    LIBRERIAS
 *****************************************************
*/
#include <espnow.h>
#include <ESP8266WiFi.h>

/*
 *****************************************************
 *    VARIABLES
 *****************************************************
*/
#define X_AXIS_PIN 32
#define Y_AXIS_PIN 33
#define SWITCH_PIN 25

// RECEIVER MAC Address
uint8_t receiverMacAddress[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};  //Here mac for Receptor (RX)

struct PacketData
{
  byte xAxisValue;
  byte yAxisValue;
  byte switchPressed;
};
PacketData data;

/*
 *****************************************************
 *    FUNCIONES
 *****************************************************
*/
//This function is used to map 0-4095 joystick value to 0-254. hence 127 is the center value which we send.
//It also adjust the deadband in joystick.
//Jotstick values range from 0-4095. But its center value is not always 2047. It is little different.
//So we need to add some deadband to center value. in our case 1800-2200. Any value in this deadband range is mapped to center 127.
int mapAndAdjustJoystickDeadBandValues(int value, bool reverse)
{
  if (value >= 2200)
  {
    value = map(value, 2200, 4095, 127, 254);
  }
  else if (value <= 1800)
  {
    value = map(value, 1800, 0, 127, 0);  
  }
  else
  {
    value = 127;
  }

  if (reverse)
  {
    value = 254 - value;
  }
  return value;
}

// callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus)
{
  Serial.print("\r\nLast Packet Send Status:\t ");
  if(sendStatus == 0){
    Serial.println("Message sent");
  }else{
    Serial.println("Message failed");
    }
}

/*
 *****************************************************
 *    INICIO
 *****************************************************
*/
void setup() 
{
  
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != 0) 
  {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  else
  {
    Serial.println("Succes: Initialized ESP-NOW");
  }
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);  //ESP_NOW_ROLE_CONTROLLER is 6
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  //ESP8266 esp_now_add_peer(uint8 mac_addr, uint8 role, uint8 channel, uint8 key, uint8 key_len)
  bool peerInfo = esp_now_add_peer(receiverMacAddress,ESP_NOW_ROLE_CONTROLLER,0,NULL,0);
  
  // Add peer        
  if (peerInfo != 0)
  {
    Serial.println("Failed to add peer");
    return;
  }
  else
  {
    Serial.println("Succes: Added peer");
  } 

  pinMode(SWITCH_PIN, INPUT_PULLUP);   
}

/*
 *****************************************************
 *    REPETICIÓN
 *****************************************************
*/
void loop() 
{
  data.xAxisValue = mapAndAdjustJoystickDeadBandValues(analogRead(X_AXIS_PIN), false);
  data.yAxisValue = mapAndAdjustJoystickDeadBandValues(analogRead(Y_AXIS_PIN), false);  
  data.switchPressed = false; 

  if (digitalRead(SWITCH_PIN) == LOW)
  {
    data.switchPressed = true;
  }

  bool result = esp_now_send(receiverMacAddress, (uint8_t *) &data, sizeof(data));
  //esp_err_t result = esp_now_send(receiverMacAddress, (uint8_t *) &data, sizeof(data));
  if (result == 0) 
  {
    Serial.println("Sent with success");
  }else{
    Serial.println("Error sending the data");
  }
  
  if (data.switchPressed == true)
  {
    delay(500);
  }
  else
  {
    delay(50);
  }
}

 

 

 

 

반응형

캐어랩 고객 지원

취업, 창업의 막막함, 외주 관리, 제품 부재!

당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약, 아이디어는 있지만 구현할 기술이 없는 막막함.

우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.

이제 고민을 멈추고, 캐어랩을 만나세요!

코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.

제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!

귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.

지난 30년 여정, 캐어랩이 얻은 모든 것을 함께 나누고 싶습니다.

카카오 채널 추가하기

카톡 채팅방에서 무엇이든 물어보세요

귀사가 성공하기까지의 긴 고난의 시간을 캐어랩과 함께 하세요.

캐어랩 온라인 채널 바로가기

캐어랩