1987년부터 2년에 한 번씩 개최되는 대회로 2017년에 출전을 했다. 호주 다윈에서부터 애들레이드까지 3022km를 태양광 자동차로 경주를 한다. 




태양광 자동차는 전기자동차와 원리가 같다. 배터리의 전기에너지로 모터를 돌려 구동된다. 태양광 자동차의 경우에는 배터리 충전을 태양전지를 이용한다. 태양광 자동차의 경우 태양전지 솔라셀, MPPT, 배터리, BMS, LDC(저전압 컨버터), 모터 인버터, 모터가 사용된다. 그 외 수많은 작은 부품들이 들어가지만, 전체적으로 저렇다. 





<솔라카 전기전자시스템>

 

 

 

완주는 못했다. 차가 너무 무거웠다. 이상

솔라카가 얼마나 더 달릴 수 있을까 (배터리 잔량 측정)


 솔라카 프로젝트에서 가장 재미있으면서도 힘겨웠던것은 배터리 잔량을 계산해서 메모리에 저장하고 이를 무선통신으로 날려서 앞의 앞의 리드카에 전송해 주는 과정이었다. 

리튬이온 배터리의 경우 배터리의 남아있는 에너지에 따라 배터리 전압이 변한다. 물론 이를 이용해서 배터리의 잔량을 계산할 수있다. 하지만 정확하지 않다. 특히나 배터리가 충,방전중일때는 배터리의 분극전압이형성되어 배터리 전압이 예상 값보다 더 떨어지거나 올라가있다. 


<

Equivalent circuit model of the lithium-ion battery.

리튬이온 배터리의 등가회로>




출처 : https://endless-sphere.com/forums/viewtopic.php?t=62932





위 그래프들은 리튬이온 전지의 방전곡선이다. 보면 방전하는 전류에따라 잔량별 전압도 다르다.


분극전압을 최소하하여 측정하려고 하면 배터리가 충방전을 하지 않고 많은 시간을 기다려야한다. 그게 휴지시간인데, 솔라카 주행을 하면서 휴지시간을 기다리며 대회를 치룰 수 없다. 

그래서 사용한 방식이 전류 적산 방식이다. 전류센서를 이용해서 방전 전류와 충전 전류를 적산하여 잔량을 계산한다. 하지만 전류적산 방식에서도 전류센서의 측정오차가 있기 때문에 오차가 누적되어 잔량에 엄청난 오차를 생기게 할 수 있다.

그래서 솔라카의 주행이 잠시 쉬는 컨트롤스탑지점이나, 밤에 주행을 중지할때의 배터리의 휴지시간을 이용하여 분극전압의 영향이 거의 없는 전압을 체크하고 전류적산 오차가 있는 배터리의 잔량을 리셋해주는 방법을 사용했다.












호주에서 작성한 솔라카 전력 회로도



호주에 도착하고 작성한 회로도이다. 우리의 전력회로도는 이렇다. 

컨버터 2개 배터리 PV모듈 모터 모터컨트롤러 등등이 들어갔다.



물론 전력회로도에 들어가지 않는 많은 전장부 모듈들이있다.






모터전력과 태양광전력을 측정하는 모듈  - 중앙 MCU로 CAN을 전송한다.

전류센서의 레졸루션이 낮아서(1.25V) 계측용증폭기를 사용해서 레졸루션을 높였다. (3.0V)

MCU는 stm32f4 사용








배터리의 전류를 측정하고 SOC(베터리 전류 잔량)을 계산하는 MCU

차량의 전원이 끊어질 경우 외부 EEPROM에 SOC를 저장한다.

SOC는 전류적산을 이용한다.

역시 CAN통신을 이용하여 중앙 MCU에 데이터를 전송한다.

전류센서의 분해능을 높이기위해 계측용증폭기 TI사의  ina333 IC를 사용했고,

stm32f4의 ADC 분해능이 4095(12bit)를 16bit로 올리기위해 TI사의 ADC IC를 사용했다.




INA333의 회로도.

이득은 오른쪽 수식으로 나온다.




양방향 전압이 아닌 단방향 전압을 인가 가능하다.





2편에서 계속











 솔라카 - CAN BUS

람세스에 사용된 CAN 통신은 태양전지로부터 나오는 전력량을 확인 할 수 있도록 사용되었다. 람세스에 탑재 되어있는 MPPT Race version4의 경우 CAN 통신을 지원하기 때문에 CAN통신 단자에 2개의 선 과 CAN컨트롤러 공급 전압(최소 6V 최대18V) 2개의 선이 필요하다. 그리고 CAN 신호를 받아서 컴퓨터로 전송 할 수 있는 모듈이 필요하다. 모듈의 경우는 마이크로프로세서로 직접 만드는 방법과 시중에 팔고있는 CAN모듈을 구입하여 사용하는 방법이 있다. 람세스에서는 직접 CAN 신호를 받아서 컴퓨터의 시리얼 통신으로 전송 할 수 있는 마이크로프로세서로 만들어 사용했다.



STM32F407 - ATA6660

CAN통신의 관한 기술문서 이기 때문에 STM32f407 ARM coretex-m4 칩을 설명 하지 않겠다.

STM32f407 CAN트랜시버를 같이 사용해야만 CAN신호를 받고 보낼 수 있다. CAN트랜시버칩은 ATMEL사의 ATA6660을 사용했다.





선을 연결 해준 뒤,  STM32f407 칩에서 CAN 신호를 받아본다.



1.1    데이터 수신

프로세서에서 CAN데이터를 받을 수 있도록 코드를 작성하여 다운로드 해준다. 아래 코드는 STM32f407 칩에서 CAN 통신을 하기 위한 레지스터 초기 설정 부분이다. 이와 같이 설정해주고, 데이터를 보내면 CAN 통신이 활성화 된다.

void Can_Init()

{

         GPIO_InitTypeDef                 GPIO_InitStructure;

         CAN_InitTypeDef                   CAN_InitStructure;

         NVIC_InitTypeDef                 NVIC_InitStructure;

 

         RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

         GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_CAN1);

         GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_CAN1);

 

         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;

         GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF;

         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

         GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;

         GPIO_Init(GPIOB, &GPIO_InitStructure);

 

         CAN_DeInit(CAN1);

 

         CAN_InitStructure.CAN_TTCM = DISABLE;

         CAN_InitStructure.CAN_ABOM = DISABLE;

         CAN_InitStructure.CAN_AWUM = DISABLE;

         CAN_InitStructure.CAN_NART = DISABLE;

         CAN_InitStructure.CAN_RFLM = DISABLE;

         CAN_InitStructure.CAN_TXFP = ENABLE;

         CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

 

        

         CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

         CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;

         CAN_InitStructure.CAN_BS2 = CAN_BS2_1tq;

         CAN_InitStructure.CAN_Prescaler = 42;

        

         CAN_Init(CAN1, &CAN_InitStructure);

 

         CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

          

         NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;

         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

         NVIC_Init(&NVIC_InitStructure);

}

 

위 코드를 STM32f407칩에 다운로드 한 뒤 시리얼 통신으로 컴퓨터에서 CAN데이터를 받아보면 7바이트의 신호를 받을 수 있다.

 

1.2    C#프로그래밍

7바이트 신호들은 각 바이트 별로 정보가 들어있다. 각 정보는 MPPT데이터 시트 표(Figure 7)에 나와있다.

각 비트 별로 신호를 받았으면 시리얼 통신으로 컴퓨터에 데이터를 넘긴 후 C#프로그램을 제작해서 읽을 수 있는 눈금으로 표시한다. 아래 소스 코드는 각 바이트를 분석해서 원하는 정보를 얻는 과정이다.

 

buff[0] = buff[7];

                    buff[7] = (byte)(buff[7] & 0x03); //하위 2비트만 살림

                    vout_data = ((buff[2] + (256 * buff[3])) * 208.79) * 0.001;

                    vin_data = ((buff[6] + (256 * buff[7])) * 150.49) * 0.001;

                    iin_data = ((buff[4] + (256 * buff[5])) * 8.12) * 0.001;

                    power_data = iin_data * vin_data;

 






CAN 수신데이터가 시리얼 통신을 거치면서 가끔씩 오류가 날 경우도 있는데 이를 잡아주기 위해 소스코드에 데이터가 온전하지 못하면 넘어오지 못하게 하는 알고리즘도 제작을 해야한다. 위처럼 CAN 통신으로 에너지정보도 받을 수 있고, 차량내 통신으로도 CAN 을 사용할 수 도 있다






모터에 전류가 어느정도 흐르는지 측정하기 위해서는 설치된 전류센서로 신호를 받아야한다. 현재 솔라카에서 사용하고 있는 전류센서[hass50]의 경우 출력 신호는 전압 신호로 되어있다.


<hass 50>


전류센서에서 출력되는 전압신호를 프로세서가 받기 위해서는 ADC(analog-to-digital converter)를 이용한다. 전압신호의 경우 노이즈가 많기 때문에 외곡이 있을 수 있고, 이 때문에 제대로된 전류측정값을 얻지 못 할 수도 있다. ADC노이즈를 줄이기위해서 솔라카에서는 디지털 필터를 사용했다. 가장 구현하기 쉬운방법이고, 개발 시간도 짧다.





'프로젝트 > 솔라카' 카테고리의 다른 글

솔라카 MPPT 전력량 CAN 데이터 수신  (0) 2018.04.17
2017 WSC 사진  (0) 2018.03.25
그래픽 oled (솔라카 대쉬보드)  (0) 2017.06.11
솔라카 고전압 측정회로  (0) 2017.05.16
MPPT 모니터링 프로그램  (0) 2016.11.25

can, rf 통신 모듈까지 장착한 후면 계기판 모습

저 모듈에서 방향지시등, 브레이크스위치 등등을 제어한다.







솔라카 계기판에 사용할 2.7인치 oled를 출력했다. (모델명: NHD-2.7-12864UCY3)

프로세서는 cortex-m3 계열 stm32f103을 사용

그래픽 라이브러리는 가장 많이 사용하는 u8g라이브러리를 이용했으며, 병렬방식이아닌 직렬방식으로 oled에 신호를 인가했다.

HAL라이브러리와 u8g라이브러리를 같이 사용했다.

속도는 직렬방식이라 느릴줄 알았는데, 계기판으로 사용하기에 전혀 지장이 없을정도로 업데이트가 빨랐다.

어느 각도에서든지 글자가 잘 보였고, 햇빛에서도 문제가 없어보였다.

이제 CAN트랜시버와 모듈화를 거쳐 CAN통신으로 값을 전달하면 값이 출력되게 만들예정이다.




아래는 데이터시트에서 발취한 시리얼 인터페이스








HAL라이브러리에 u8g_arm.c , u8g_arm.h 를 추가하여 소스를 추가한다.







u8g_arm.c
 #include "u8g_arm.h"  
 void u8g_Delay(uint16_t val)  
 {  
      HAL_Delay(val);  
 }  
 void u8g_MicroDelay(void)  
 {  
      HAL_Delay(1);  
 }  
 void u8g_10MicroDelay(void)  
 {  
      HAL_Delay(1);  
 }  
 uint8_t u8g_com_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)  
 {  
  switch(msg)  
  {  
   case U8G_COM_MSG_STOP:  
    break;  
   case U8G_COM_MSG_INIT:  
    u8g_MicroDelay();  
    break;  
   case U8G_COM_MSG_ADDRESS:           /* define cmd (arg_val = 0) or data mode (arg_val = 1) */  
    u8g_10MicroDelay();  
    HAL_GPIO_WritePin(PORT, DC, arg_val);  
    u8g_10MicroDelay();  
    break;  
   case U8G_COM_MSG_CHIP_SELECT:  
    if ( arg_val == 0 )  
    {  
         HAL_Delay(1);  
         HAL_GPIO_WritePin(PORT, CS, GPIO_PIN_SET);  
    }  
    else  
      HAL_GPIO_WritePin(PORT, CS, GPIO_PIN_RESET);  
    u8g_MicroDelay();  
    break;  
   case U8G_COM_MSG_RESET:  
    break;  
   case U8G_COM_MSG_WRITE_BYTE:  
     HAL_SPI_Transmit(&SPI_HANDLER, &arg_val, 1, 10000);  
     while(HAL_SPI_GetState(&SPI_HANDLER) != HAL_SPI_STATE_READY);  
     u8g_MicroDelay();  
     break;  
   case U8G_COM_MSG_WRITE_SEQ:  
   case U8G_COM_MSG_WRITE_SEQ_P:  
    {  
         HAL_SPI_Transmit(&SPI_HANDLER, (uint8_t *)arg_ptr, arg_val, 10000);  
         while(HAL_SPI_GetState(&SPI_HANDLER) != HAL_SPI_STATE_READY);  
         u8g_MicroDelay();  
         arg_val = 0;  
    }  
    break;  
  }  
  return 1;  
 }  

u8g_arm.h:

 #ifndef _U8G_ARM_H  
 #define _U8G_ARM_H  
 #include "u8g.h"  
 #include "stm32f1xx_hal.h"  
 #define SPI_HANDLER hspi2 // use your SPI hadler  
 extern SPI_HandleTypeDef SPI_HANDLER;  
 #define DC GPIO_PIN_11  
 #define CS GPIO_PIN_12  
 #define PORT GPIOB  
 uint8_t u8g_com_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);  
 #endif  

and part of main.c:  메인소스는 재량껏 수정한다.
 #include "stm32f1xx_hal.h"  
   
 /* USER CODE BEGIN Includes */  
 #include "u8g.h"  
 #include "u8g_arm.h"  
 /* USER CODE END Includes */  
   
 /* Private variables ---------------------------------------------------------*/  
 SPI_HandleTypeDef hspi2;  
   
 TIM_HandleTypeDef htim1;  
   
 /* USER CODE BEGIN PV */  
 u8g_t u8g;  
 /* Private variables ---------------------------------------------------------*/  
   
 /* USER CODE END PV */  
   
 /* Private function prototypes -----------------------------------------------*/  
 void SystemClock_Config(void);  
 static void MX_GPIO_Init(void);  
 static void MX_SPI2_Init(void);  
   
   
 /* USER CODE BEGIN PFP */  
 /* Private function prototypes -----------------------------------------------*/  
   
 /* USER CODE END PFP */  
   
 /* USER CODE BEGIN 0 */  
   
 /* USER CODE END 0 */  
   
 int main(void)  
 {  
   
  /* USER CODE BEGIN 1 */  
   
  /* USER CODE END 1 */  
   
  /* MCU Configuration----------------------------------------------------------*/  
   
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */  
  HAL_Init();  
   
  /* Configure the system clock */  
  SystemClock_Config();  
   
  /* Initialize all configured peripherals */  
  MX_GPIO_Init();  
  MX_SPI2_Init();  
   
   
  /* USER CODE BEGIN 2 */  
  u8g_InitComFn(&u8g, &u8g_dev_ssd1306_128x64_hw_spi, u8g_com_hw_spi_fn); //이부분은 자신의 디스플레이에 맞춰야함 
  HAL_Delay(100);  
  /* USER CODE END 2 */  
   
  /* Infinite loop */  
  /* USER CODE BEGIN WHILE */  
  while (1)  
  {  
  /* USER CODE END WHILE */  
   
  /* USER CODE BEGIN 3 */  
       u8g_FirstPage(&u8g);  
       do  
       {  
            u8g.font = u8g_font_profont22;  
            u8g_DrawStr(&u8g, 20, 55, "Hello");  
       } while ( u8g_NextPage(&u8g) );  
    HAL_Delay(100);  
  }  
  /* USER CODE END 3 */  
   
 }  




spi+hal+u8g 

도움받은곳 http://elastic-notes.blogspot.kr/p/stm32-spi-oled-ssd1306-u8glib-cubemx.html






'프로젝트 > 솔라카' 카테고리의 다른 글

2017 WSC 사진  (0) 2018.03.25
솔라카 전류측정[adc 정확도 향상]  (0) 2017.07.10
솔라카 고전압 측정회로  (0) 2017.05.16
MPPT 모니터링 프로그램  (0) 2016.11.25
솔라카 더미카  (0) 2016.10.15








INA333 계측용 증폭기를 사용했다. 전압분배 저항은 200k 근처로 사용해서 내부임피던스를 높이고, 용량이 큰 저항을 사용해야한다. 

pspice 시뮬레이션 결과 배터리 전압이 70V일 경우 2.5V가 출력 되고 배터리 전압이 121.8V 일 경우 4.5V가 출력이 된다.

MCU의 12bit ADC로 배터리의 전압을 측정 할 수 있다. 하지만 배터리는 고전압으로 제어회로에 심각한 피해를 줄 수 있고, BLDC모터의 토크리플 때문에 노이즈로 센싱 성능이 떨어진다. 그래서 절연 과정과 아날로그 필터, 디지털 필터가 필요하다. 

'프로젝트 > 솔라카' 카테고리의 다른 글

솔라카 전류측정[adc 정확도 향상]  (0) 2017.07.10
그래픽 oled (솔라카 대쉬보드)  (0) 2017.06.11
MPPT 모니터링 프로그램  (0) 2016.11.25
솔라카 더미카  (0) 2016.10.15
방향지시등 회로 - 555타이머  (0) 2016.09.01

솔라셀 상판 전력데이터가 필요했는데

전력측정하는 시스템을 만들자니 번거럽고해서, mppt에서 나오는 CAN데이터를 받아왔다.

 

 

구름이 걷힐때 까지 기다리면서 

??

 

구름이 걷혔다.

 

 

 

 

 

해가 그리 밝지 않았다..

 

 

 

 

buff[0] = buff[7];
buff[7] = (byte)(buff[7] & 0x03); //하위 2비트만 살림
vout_data = ((buff[2] + (256 * buff[3])) * 208.79) * 0.001;
vin_data = ((buff[6] + (256 * buff[7])) * 150.49) * 0.001;
iin_data = ((buff[4] + (256 * buff[5])) * 8.12) * 0.001;
power_data = iin_data * vin_data;

 

 

 

 

 

c# 으로 간단하게 제작

 

'프로젝트 > 솔라카' 카테고리의 다른 글

솔라카 전류측정[adc 정확도 향상]  (0) 2017.07.10
그래픽 oled (솔라카 대쉬보드)  (0) 2017.06.11
솔라카 고전압 측정회로  (0) 2017.05.16
솔라카 더미카  (0) 2016.10.15
방향지시등 회로 - 555타이머  (0) 2016.09.01


대회전 연습용 차량이다.

+ Recent posts