Mini-Project

>>> ดาวน์โหลดรายงานสำหรับ Mini-Project ที่นี่ <<<
 
หัวข้อเรื่อง การวัดกระแสและแรงดันของวงจรไฟฟ้า

จัดทำโดย

นายธัชกร           คุ้นเคย       รหัสนักศึกษา 5501012630133  สาขา Cpr.E
นายรุ่งโรจน์       กุลพันธ์     รหัสนักศึกษา 5501012630249  สาขา Cpr.E


1. ข้อกำหนดเบื้องต้น

   1.1. ใช้บอร์ด MCU ตามที่ได้รับและทดลองใช้งาน คือบอร์ด STM32F3Discovery
   1.2. มีการนำเสนอข้อมูลสถานะการทำงานของระบบ หรือควบคุมการสั่งงานผ่านหน้าเว็บ
   1.3. มีการใช้งานบัส I2C หรือ SPI อย่างน้อย 1 อุปกรณ์
   1.4. มีการบันทึกข้อมูลลง SD card/microSD หรือส่งข้อมูลแบบไร้สายไปยังคอมพิวเตอร์(ห้ามใช้อุปกรณ์ประเภท WiFi-to-Serial) หรือส่งข้อมูลผ่าน Ethernet ไปยังคอมพิวเตอร์

2. วัตถุประสงค์ของงาน
    2.1 เพื่ออ่านข้อมูลกระแสจากแรงดันเอาต์พุตของโมดูล ACS712 โดยใช้บอร์ด STM32F3Discovery
    2.2 เพื่ออ่านข้อมูลแรงดันของวงจรไฟฟ้าผ่าน ADC ของบอร์ด STM32F3Discovery
    2.3  เพื่อใช้งานโมดูล Ethernet โดยใช้บัส SPI ของบอร์ด STM32F3Discovery
    2.4 เพื่อแสดงผลกราฟิกของค่าที่อ่านได้ผ่านทางหน้าเว็บ โดยส่งและดึงข้อมูลใน IoT cloud โดยใช้บริการของเว็บ Plot.ly
    2.5 เพื่อเรียนรู้การเขียนหน้าเว็บเพื่อแสดงผลกราฟ
 
3. ประโยชน์ที่คาดว่าจะได้รับ
    3.1 มีความรู้ ความเข้าใจในการใช้ C/C++ เพื่อใช้งานรวมกับ HAL Library ของบอร์ด STM32F3Discovery
    3.2 สามารถใช้วัดกระแสและแรงดันของวงจรไฟฟ้า แล้วสามารถเรียกดูข้อมูลผลการวัดผ่านทางหน้าเว็บ
    3.3  เรียนรู้การทำงานเป็นกลุ่มและการแบ่งงานอย่างเหมาะสม

4. ขอบเขตของงาน
    4.1 ในการวัดกระแสของวงจรไฟฟ้าจะใช้โมดูล ACS712
    4.2 ในการส่งข้อมูลผ่าน Ethernet จะใช้โมดูล ENC28J60
    4.3 บอร์ดที่ใช้สำหรับการควบคุมการทำงานจะใช้บอร์ด STM32F3Discovery
    4.4 เว็บสำหรับ IoT Cloud ที่เลือกใช้งานคือ http://www.plot.ly 

5.  การแบ่งงานในกลุ่ม

รายการ
ผู้รับผิดชอบ
การอ่านค่าแรงดันเอาต์พุตจากโมดูล ACS712 และแรงดันของวงจรไฟฟ้า
ธัชกร
การส่งค่ากระแสและแรงดันไฟฟ้าที่อ่านได้ไปยังโมดูล Ethernet
ธัชกร
การอ่านค่ากระแสจาก Ethernet
รุ่งโรจน์
การแสดงผลค่ากระแสผ่านหน้าเว็บ
รุ่งโรจน์

 
6. การออกแบบระบบเบื้องต้น

แผนภาพสำหรับการออกแบบระบบเบื้องต้นแสดงดังภาพด้านล่าง


ภาพแสดง แผนภาพแสดงการทำงานของระบบโดยรวม


               การทำงานจะเริ่มจากการอ่านค่าแรงดันเอาต์พุตแบบ Analog ที่ได้จาก ACS712 Module ที่ใช้สำหรับการวัดกระแสโดยใช้ ADC1 ของบอร์ด STM32F3Discovery แล้วอ่านค่าแรงดันเอาต์พุตที่ได้จากวงจรไฟฟ้าโดยใช้ ADC2 ของบอร์ด STM32F3Discovery หลังจากนั้นจะส่งค่าที่อ่านได้ไปยังโมดูล Ethernet โดยผ่านระบบบัสแบบ SPI แล้วข้อมูลจะถูกส่งผ่านสาย LAN ไปยังคอมพิวเตอร์เพื่อจะนำข้อมูลมาแสดงผลในหน้าเว็บ

7. การทดลองระบบย่อย     
    7.1 ทดลองการใช้งาน SPI เพื่อใช้เชื่อมต่อระหว่างบอร์ด STM32F3Discovery กับ Module Ethernet ENC28J60 อ่านบทความ
    7.2 ทดลองการใช้งาน ADC (Analog Digital Converter) ของบอร์ด STM32F3Discovery เพื่อใช้ในการอ่านค่า Module วัดกระแสและค่าแรงดันของวงจรไฟฟ้า อ่านบทความ
    7.3 ทดลองอ่านค่าจาก ADC ของบอร์ด STM32F3Discovery และส่งค่าที่ได้ผ่านโมดูล Ethernet โดยใช้ UDP Protocol อ่านบทความ
    7.4 ทดลองการใช้งาน Socket , Plotly ในส่วนของการรับข้อมูลในคอมพิวเตอร์ อ่านบทความ
    7.5 การปรับค่าต่างๆ ในกราฟ (Plotly) อ่านบทความ

ผลการทดลอง
  • อุปกรณ์ที่ต้องใช้
    • คอมพิวเตอร์ สำหรับรับข้อมูลผ่าน Ethernet และแสดงผลข้อมูลผ่านหน้าเว็บ
    • บอร์ด STM32F3Discovery สำหรับรับข้อมูลกระแส และแรงดันของวงจรไฟฟ้า และส่งข้อมูลผ่านบัส SPI ไปยังโมดูล Ethernet
บอร์ด STM32F3Discovery

    • โมดูล Ethernet ENC28J60


โมดูล ENC28J60 สำหรับเชื่อมต่อเครือข่าย Ethernet

        สำหรับโมดูล Ethernet ใช้ระดับแรงดันไฟเลี้ยง 3.3V และสามารถควบคุมการทำงานผ่านระบบบัสแบบ SPI ใช้ในการส่งข้อมูลกระแส และแรงดันของวงจรไฟฟ้าที่วัดได้ไปยังคอมพิวเตอร์ สามารถอ่านบทความเกี่ยวกับโมดูลได้ ที่นี่
   
    • โมดูล ACS712 สำหรับอ่านค่ากระแสไฟฟ้า
   
ภาพแสดงโมดูล ACS712
        โมดูลที่ใช้วัดกระแสซึ่งเมื่อวัดค่าแล้วเอาท์พุตจะเป็นค่า Voltage ซึ่งค่าที่ได้จะอ่านโดย STM32F3Discovery สามารถอ่านบทความเกี่ยวกับโมดูล ACS712 ได้ ที่นี่

    • สายไฟสำหรับต่อวงจร และเครื่องมือวัดต่างๆ เช่น ออสซิลโลสโคปมัลติมิเตอร์ ฯลฯ
    • ตัวต้านทานขนาด 10จำนวน 2 ตัว
    • แหล่งจ่ายไฟกระแสตรง


  • ขั้นตอนการทดลอง
        1. ทำการเขียนโค้ดเพื่อควบคุมการทำงานของบอร์ด STM32F3Discovery โดยนำส่วนต่างๆ ที่ได้ทำการทดลองใน บทที่ 3 มารวมกันเพื่อให้ทำงานเป็นระบบหนึ่งเดียวกัน ซึ่งมีโค้ดดังต่อไปนี้
    /**
      ******************************************************************************
      * File Name          : main.c
      * Date               : 07/06/2015 16:19:20
      * Description        : Main program body
      ******************************************************************************
      *
      * COPYRIGHT(c) 2015 STMicroelectronics
      *
      * Redistribution and use in source and binary forms, with or without modification,
      * are permitted provided that the following conditions are met:
      *   1. Redistributions of source code must retain the above copyright notice,
      *      this list of conditions and the following disclaimer.
      *   2. Redistributions in binary form must reproduce the above copyright notice,
      *      this list of conditions and the following disclaimer in the documentation
      *      and/or other materials provided with the distribution.
      *   3. Neither the name of STMicroelectronics nor the names of its contributors
      *      may be used to endorse or promote products derived from this software
      *      without specific prior written permission.
      *
      * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
      * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
      * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
      * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
      * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      *
      ******************************************************************************
      */
    
    /* Includes ------------------------------------------------------------------*/
    #include "stm32f3xx_hal.h"
    
    /* USER CODE BEGIN Includes */
    #include <UIPEthernet.h>
    #include <stdio.h>
    #include <string.h>
    /* USER CODE END Includes */
    
    /* Private variables ---------------------------------------------------------*/
    ADC_HandleTypeDef hadc1;
    ADC_HandleTypeDef hadc2;
    
    SPI_HandleTypeDef hspi3;
    
    /* USER CODE BEGIN PV */
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_ADC1_Init(void);
    static void MX_ADC2_Init(void);
    static void MX_SPI3_Init(void);
    
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* USER CODE BEGIN 0 */
    UIPEthernetClass UIPEthernet(&hspi3, GPIOA, GPIO_PIN_15);
    EthernetUDP udp;
    
    // Function for Start and get data from ADC1(PIN: PF2)
    uint32_t readADC1(){
        // Start ADC1
        HAL_ADC_Start(&hadc1);
        // wait for ADC1 conversion finished
        while(__HAL_ADC_GET_FLAG(&hadc1, ADC_FLAG_EOC) == RESET);
        // return value from ADC1
        return HAL_ADC_GetValue(&hadc1);
    }
    
    // Function for Start and get data from ADC2(PIN: PB2)
    uint32_t readADC2(){
        // Start ADC2
        HAL_ADC_Start(&hadc2);
        // wait for ADC2 conversion finished
        while(__HAL_ADC_GET_FLAG(&hadc2, ADC_FLAG_EOC) == RESET);
        // return value from ADC2
        return HAL_ADC_GetValue(&hadc2);
    }
    /* 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_ADC1_Init();
      MX_ADC2_Init();
      MX_SPI3_Init();
    
      /* USER CODE BEGIN 2 */
        // set initial value for Ethernet protocol
        // set MAC Address of MCU + ENC28J60
        const uint8_t   MAC_ADDR[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};
        // set IP Address of MCU + ENC28J60
        const IPAddress SOURCE_IP(192, 168, 1, 200);
        // set IP Address of Computer for receive data
        const IPAddress DESTINATION_IP(192, 168, 1, 33);
        // set receive data port for MCU + ENC28J60
        const uint16_t  RECEIV_PORT = 32000;
        // set transmit data port for MCU + ENC28J60
        const uint16_t  TRANS_PORT = 42000;
        // set DNS, Default Gateway and Subnet Mask
        // that should change value of each difference network
        const IPAddress DNS(192, 168, 1, 1);
        const IPAddress GATEWAY(192, 168, 1, 1);
        const IPAddress SUBNET(255, 255, 255, 0);
    
        // Start ENC28J60
        UIPEthernet.begin(MAC_ADDR, SOURCE_IP, DNS, GATEWAY, SUBNET);
        udp.begin(RECEIV_PORT);
        char packetBuffer[1000];
    
        // Set /CS Pin as High
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
    
        UIPEthernet.network.linkStatus();
    
        // Start UDP Protocol
        udp.begin(RECEIV_PORT);
    
        // Set some LED for tell state of start Ethernet
        HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, GPIO_PIN_SET);
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
      /* USER CODE END WHILE */
    
      /* USER CODE BEGIN 3 */
        // Start send current and voltage
        // format current[0:11], voltage[0:11]
        bool success = udp.beginPacket(DESTINATION_IP, TRANS_PORT);
        // get current data from ADC1
        uint32_t current_data = readADC1();
        // get voltage data from ADC2
        uint32_t voltage_data = readADC2();
        int i;
        // send current data MSB first
        for(i = 11; i >= 0; i--){
                uint8_t send;
                if((current_data >> i) & 1)
                    send = '1';
                else
                    send = '0';
                udp.write((uint8_t)send);
        }
        udp.write((uint8_t)',');
        // send voltage data MSB first
        for(i = 11; i >= 0; i--){
                uint8_t send;
                if((voltage_data >> i) & 1)
                    send = '1';
                else
                    send = '0';
                udp.write((uint8_t)send);
        }
        udp.endPacket();
        HAL_Delay(50);
        // if send packet success blinking some LED
        if(success)
            HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_10);
        // if send packet not success blinking some LED
        else
            HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_11);
      }
      /* USER CODE END 3 */
    
    }
    
    /** System Clock Configuration
    */
    void SystemClock_Config(void)
    {
    
      RCC_OscInitTypeDef RCC_OscInitStruct;
      RCC_ClkInitTypeDef RCC_ClkInitStruct;
      RCC_PeriphCLKInitTypeDef PeriphClkInit;
    
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
      RCC_OscInitStruct.HSIState = RCC_HSI_ON;
      RCC_OscInitStruct.HSICalibrationValue = 16;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
      RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
      HAL_RCC_OscConfig(&RCC_OscInitStruct);
    
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
      HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
    
      PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
      PeriphClkInit.Adc12ClockSelection = RCC_ADC12PLLCLK_DIV1;
      HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
    
      __SYSCFG_CLK_ENABLE();
    
    }
    
    /* ADC1 init function */
    void MX_ADC1_Init(void)
    {
    
      ADC_ChannelConfTypeDef sConfig;
    
        /**Common config
        */
      hadc1.Instance = ADC1;
      hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC;
      hadc1.Init.Resolution = ADC_RESOLUTION12b;
      hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
      hadc1.Init.ContinuousConvMode = DISABLE;
      hadc1.Init.DiscontinuousConvMode = DISABLE;
      hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
      hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
      hadc1.Init.NbrOfConversion = 1;
      hadc1.Init.DMAContinuousRequests = DISABLE;
      hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
      hadc1.Init.LowPowerAutoWait = DISABLE;
      hadc1.Init.Overrun = OVR_DATA_OVERWRITTEN;
      HAL_ADC_Init(&hadc1);
    
        /**Configure Regular Channel
        */
      sConfig.Channel = ADC_CHANNEL_10;
      sConfig.Rank = 1;
      sConfig.SingleDiff = ADC_SINGLE_ENDED;
      sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
      sConfig.OffsetNumber = ADC_OFFSET_NONE;
      sConfig.Offset = 0;
      HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    }
    
    /* ADC2 init function */
    void MX_ADC2_Init(void)
    {
    
      ADC_ChannelConfTypeDef sConfig;
    
        /**Common config
        */
      hadc2.Instance = ADC2;
      hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC;
      hadc2.Init.Resolution = ADC_RESOLUTION12b;
      hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
      hadc2.Init.ContinuousConvMode = DISABLE;
      hadc2.Init.DiscontinuousConvMode = DISABLE;
      hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
      hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
      hadc2.Init.NbrOfConversion = 1;
      hadc2.Init.DMAContinuousRequests = DISABLE;
      hadc2.Init.EOCSelection = EOC_SINGLE_CONV;
      hadc2.Init.LowPowerAutoWait = DISABLE;
      hadc2.Init.Overrun = OVR_DATA_OVERWRITTEN;
      HAL_ADC_Init(&hadc2);
    
        /**Configure Regular Channel
        */
      sConfig.Channel = ADC_CHANNEL_12;
      sConfig.Rank = 1;
      sConfig.SingleDiff = ADC_SINGLE_ENDED;
      sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
      sConfig.OffsetNumber = ADC_OFFSET_NONE;
      sConfig.Offset = 0;
      HAL_ADC_ConfigChannel(&hadc2, &sConfig);
    
    }
    
    /* SPI3 init function */
    void MX_SPI3_Init(void)
    {
    
      hspi3.Instance = SPI3;
      hspi3.Init.Mode = SPI_MODE_MASTER;
      hspi3.Init.Direction = SPI_DIRECTION_2LINES;
      hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
      hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
      hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
      hspi3.Init.NSS = SPI_NSS_SOFT;
      hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
      hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
      hspi3.Init.TIMode = SPI_TIMODE_DISABLED;
      hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
      hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLED;
      HAL_SPI_Init(&hspi3);
    
    }
    
    /** Configure pins as
            * Analog
            * Input
            * Output
            * EVENT_OUT
            * EXTI
         PA5   ------> SPI1_SCK
         PA6   ------> SPI1_MISO
         PA7   ------> SPI1_MOSI
         PA11   ------> USB_DM
         PA12   ------> USB_DP
         PB6   ------> I2C1_SCL
         PB7   ------> I2C1_SDA
    */
    void MX_GPIO_Init(void)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct;
    
      /* GPIO Ports Clock Enable */
      __GPIOE_CLK_ENABLE();
      __GPIOC_CLK_ENABLE();
      __GPIOF_CLK_ENABLE();
      __GPIOA_CLK_ENABLE();
      __GPIOB_CLK_ENABLE();
    
      /*Configure GPIO pins : PE2 PE4 PE5 PE0
                               PE1 */
      GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_0
                              |GPIO_PIN_1;
      GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    
      /*Configure GPIO pins : PE3 PE8 PE9 PE10
                               PE11 PE12 PE13 PE14
                               PE15 */
      GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
                              |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
                              |GPIO_PIN_15;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
      HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    
      /*Configure GPIO pin : PA0 */
      GPIO_InitStruct.Pin = GPIO_PIN_0;
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pins : PA5 PA6 PA7 */
      GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
      GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pins : PA11 PA12 */
      GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
      GPIO_InitStruct.Alternate = GPIO_AF14_USB;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pins : PB6 PB7 */
      GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
      GPIO_InitStruct.Pull = GPIO_PULLUP;
      GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
      GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
      HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
        /*Configure GPIO pins : PA15*/
      GPIO_InitStruct.Pin = GPIO_PIN_15;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
    #ifdef USE_FULL_ASSERT
    
    /**
       * @brief Reports the name of the source file and the source line number
       * where the assert_param error has occurred.
       * @param file: pointer to the source file name
       * @param line: assert_param error line source number
       * @retval None
       */
    void assert_failed(uint8_t* file, uint32_t line)
    {
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
        ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    
    }
    
    #endif
    
    /**
      * @}
      */
    
    /**
      * @}
    */
    
    /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    
    
        จากโค้ดจะใช้ ADC1 จำนวน 12 บิตสำหรับอ่านแรงดันเอาต์พุตจากโมดูลวัดกระแส ACS712, ADC2 จำนวน 12 บิตสำหรับอ่านแรงดันของวงจรไฟฟ้า และใช้ SPI3 สำหรับเชื่อมต่อบัส SPI กับโมดูล Ethernet ENC28J60
          2. ทำการต่อวงจรสำหรับการทดลองดังต่อไปนี้
 
แผนภาพการต่อวงจรของระบบทั้งหมด
         สำหรับวงจรที่นำมาใช้สำหรับการทดลอง จะนำตัวต้านทาน 10Ω จำนวน 2 ตัวมาต่อขนานกัน แล้วจ่ายแรงดันด้วยเครื่องจ่ายไฟกระแสตรงขนาด 3V

        3. ทำการรันโค้ด Python ในไฟล์ receive_and_send.py ในคอมพิวเตอร์เพื่อรับข้อมูลที่ได้จากบอร์ด STM32F3 Discovery
ซึ่งมีโค้ดดังต่อไปนี้
# -*- coding: utf-8 -*-
import socket,SocketServer,time
from sent2plotly import *
import webbrowser
import datetime
import httplib, urllib

print 'Server started...' #print server start
host, port = '0.0.0.0',42000 #set host and port
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
server.bind((host,port))
server.settimeout(5)

plot_cur = Sent2plotly(0, "Plot-current", "Current")
plot_vol = Sent2plotly(1, "Plot-Voltage", "Voltage")
plot_watt = Sent2plotly(2, "Plot-watt", "Watt")
webbrowser.open_new_tab("index.html") #open index.html

i=0
start_time = time.time()
vcc_half = 5
vcc_half = vcc_half/2.0
try:
  while True:
    try:
      # wait for some data
      (data, addr) = server.recvfrom(65535)
      
      # if data is "current" it mean some one want to send current data
      if data :
        cur_data , vol_data  = data.split(",")
        voltage_data = int(vol_data, 2)
        current_data = int(cur_data, 2)
        print i, ': from', str(addr), 'data is(binary) ', vol_data , cur_data, ' and Integer is ', voltage_data, current_data
        
        
        x = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
        current_data = (current_data/4095.0)*3.0
        current_data = (current_data - vcc_half)/0.185 # find true current
        plot_cur.plot(x, current_data) #plot graph
        
        
        voltage_data = (voltage_data/4095.0)*3.0
        plot_vol.plot(x, voltage_data) #plot graph
        plot_watt.plot(x, current_data*voltage_data)
        
        print "v = ", voltage_data , "c = " , current_data
        i += 1
        
    
    except socket.timeout:
      print "Out"
      pass
except KeyboardInterrupt as ex:
  print ex
        สำหรับโค้ดในไฟล์ receive_and_send.py ที่เราเรียกใช้งานนั้น จะมีการเรียกใช้งานคลาสที่อยู่ภายในไฟล์ sent2plotly.py เพื่อใช้สำหรับการส่งข้อมูลต่างๆ ไปยังเว็บ Plot.py โดยมมีโค้ดดังต่อไปนี้ 

#!/usr/bin/env python
#sent2plotly.py
import plotly
import plotly.plotly as py
import plotly.tools as tls
import datetime
import time
from plotly.graph_objs import *

class Sent2plotly(object):
    def __init__(self,choose_stream_id, filename, title):
        self.filename = filename
        self.title = title
        self.dataX = 0.0
        self.dataY = 0.0
        
        py.sign_in('tachagon', 'e3xdl3rnqe')
        stream_ids=["5oedue6mq7", "thg9gb1wwd", "p8x1frf0qx"]
        tls.set_credentials_file(stream_ids)
        
        # Get stream id from stream id list
        stream_id = stream_ids[choose_stream_id]
        # Make instance of stream id object
        stream = Stream(
            token=stream_id,    # link stream id to 'token' key
            maxpoints=80        # keep a max of 80 pts on screen
        )
        
        # Initialize trace of streaming plot by embedding the unique stream_id
        trace1 = Scatter(
            x=[],
            y=[],
            mode='lines+markers',
            stream=stream       # embed stream id, 1 per trace
        )
        
        data = Data([trace1])
        
        # Add title to layout object
        layout = Layout(title=self.title)
        
        # Make a figure object
        fig = Figure(data=data, layout=layout)
        
        #(@) Send fig to Plotly, initialize streaming plot, open new tab
        unique_url = py.plot(fig, filename=self.filename , auto_open=False)
        
        # (@)   Make instance of the Stream link object,
        #       with same stream id as Stream id object
        self.s = py.Stream(stream_id)
        
        #(@) Open the stream
        self.s.open()
    
    def plot(self, dataX, dataY):
        self.dataX = dataX
        self.dataY = dataY
        self.s.write(dict(x=self.dataX, y=self.dataY))
    
    def end(self):
        self.s.close()
    

         4. ทำการเปิดไฟล์ index.html เพื่อแสดงผลหน้าเว็บ โดยมีโค้ด HTML ดังต่อไปนี้

<!DOCTYPE html>

<html>
<head>
    <title>Miniproject Embedded</title>
    <link rel="stylesheet" type="text/css" href="./stylesheet/applications.css">
</head>

<body>
<center>
<div id="page-wrap" >
    <h1>Current</h1>
    <iframe width="800" height="600" frameborder="0" seamless="seamless" scrolling="no" src="https://plot.ly/~tachagon/95.embed?width=800&height=600"></iframe>
    <h1>Voltage</h1>
    <iframe width="800" height="600" frameborder="0" seamless="seamless" scrolling="no" src="https://plot.ly/~tachagon/97.embed?width=800&height=600"></iframe>
    <h1>Watt</h1>
    <iframe width="800" height="600" frameborder="0" seamless="seamless" scrolling="no" src="https://plot.ly/~tachagon/103.embed?width=800&height=600"></iframe>
    <div id="credit" >
    <h2 align="left">made by</h2>
    <p align="left">
        Tatchagon Koonkoei 55010126<br>
        Rungroj Kulapan 5501012630249<br><br>
    </p>
    </div>
</div>
</center>
</body>
</html>

        สำหรับหน้าเว็บที่แสดงผลจะมีการจัดรูปแบบการแสดงผลให้สวยงามด้วยโค้ด CSS ซึ่งมีโค้ดดังต่อไปนี้ 

body{
    background: url("./bg.jpg") no-repeat fixed;
    background-attachment:scoll;
    background-size: 100% auto;
}
#page-wrap{
    background: url("./bg.jpg") no-repeat fixed;
    width: 1100px;
    margin: 40px auto;
    padding: 0;
    margin-left: auto;
}
#credit{
    width: 1100px;
    margin: 50px auto;
    padding: 0;
    margin-left: 20px ;
}
h1{
    color: #FFFF99;
    font-family: 'Times New Roman', Georgia, Serif;
}
h2{
    color: white;
    font-family: "Comic Sans MS", cursive, sans-serif;
}
p{
    color: #FFFF99;
    font-family: "Comic Sans MS", cursive, sans-serif;
    margin-left: auto;
}


  • ภาพผลการทดลอง
ภาพการต่อวงจรทดลอง
 
ภาพการวัดค่ากระแสไฟฟ้า และแรงดันไฟฟ้าที่ได้จากวงจร
ภาพค่าที่ได้จากการรับข้อมูลกระแสไฟฟ้า และแรงดันไฟฟ้าในคอมพิวเตอร์ด้วยโค้ด Python
 
กราฟข้อมูลของการวัดกระแสไฟฟ้า ที่ได้จากการทำงานของระบบ
 
กราฟข้อมูลของการวัดแรงดันไฟฟ้า ที่ได้จากการทำงานของระบบ

        เนื่องจากภาพกราฟของเอาต์พุตที่ได้จะมีลักษณะเป็นกราฟที่ปรับสเกลตามข้อมูลที่มีอยู่ ดังนั้นเราจึงพบว่ากราฟจะมีลักษณะเกว่งขึ้นลงมาก ทั้งที่ข้อมูลมีค่าไม่ต่างกันมาก เพราะฉะนั้นเราจึงได้มีการปรับโค้ด Python ภายในไฟล์ sent2plotly.py เพื่อให้มีการกำหนดสเกลของกราฟที่แน่นอนเพื่อให้ภาพกราฟที่ออกมานั้นสามารถอ่านค่าได้ง่าย และสามารถมองภาพได้เข้าใจง่ายมากยิ่งขึ้น โดยมีโค้ดดังนี้
#!/usr/bin/env python
#sent2plotly.py
import plotly
import plotly.plotly as py
import plotly.tools as tls
import datetime
import time
from plotly.graph_objs import *

class Sent2plotly(object):
    def __init__(self,choose_stream_id, filename, title):
        self.filename = filename
        self.title = title
        self.dataX = 0.0
        self.dataY = 0.0
        
        py.sign_in('tachagon', 'e3xdl3rnqe')
        stream_ids=["5oedue6mq7", "thg9gb1wwd", "p8x1frf0qx"]
        tls.set_credentials_file(stream_ids)
        
        # Get stream id from stream id list
        stream_id = stream_ids[choose_stream_id]
        # Make instance of stream id object
        stream = Stream(
            token=stream_id,    # link stream id to 'token' key
            maxpoints=80        # keep a max of 80 pts on screen
        )
        
        # Initialize trace of streaming plot by embedding the unique stream_id
        trace1 = Scatter(
            x=[],
            y=[],
            mode='lines+markers',
            stream=stream       # embed stream id, 1 per trace
        )
        
        data = Data([trace1])
        range_x = [0,0];
        range_y = [0,0];
        # Add title to layout object
        if(choose_stream_id == 0):
            range_x = [0, 30]
            range_y = [-3,3]
        else:
            range_x = [0, 30]
            range_y = [0,5]
        
        layout1 = Layout(title=self.title,
                        yaxis=YAxis(range=[range_y[0], range_y[1]]))
        
        
        # Make a figure object
        fig = Figure(data=data, layout=layout1)
        
        #(@) Send fig to Plotly, initialize streaming plot, open new tab
        unique_url = py.plot(fig, filename=self.filename , auto_open=False)
        
        # (@)   Make instance of the Stream link object,
        #       with same stream id as Stream id object
        self.s = py.Stream(stream_id)
        
        #(@) Open the stream
        self.s.open()
    
    def plot(self, dataX, dataY):
        self.dataX = dataX
        self.dataY = dataY
        self.s.write(dict(x=self.dataX, y=self.dataY))
    
    def end(self):
        self.s.close()

        เมื่อมีการเปลี่ยนแปลงโค้ดภายในไฟล์ sent2plotly.py แล้ว จะได้ภาพของกราฟที่มีการปรับสเกลแล้วดังภาพด้านล่าง
กราฟแสดงค่ากระแสไฟฟ้า หลังจากมีการกำหนดสเกลของกราฟ
 
กราฟแสดงค่าแรงดันไฟฟ้า หลังจากมีการกำหนดสเกลของกราฟ
 
กราฟแสดงค่าวัตต์ หลังจากการกำหนดสเกลของกราฟ
ภาพสัญญาณเอาต์พุตสำหรับความถี่ในการส่งข้อมูลด้วยบอร์ด STM32Discovery
 
ภาพสัญญาณเอาต์พุตสำหรับความถี่ในการส่งข้อมูลด้วยบอร์ด STM32Discovery
        จากภาพสัญญาณเอาต์พุตด้านบน จะเป็นสัญญาณเอาต์พุตที่ได้จากการวัดความถี่ในการส่งข้อมูลแต่ละครั้งของบอร์ด STM32F3Discovery ซึ่งจะมีการ Toggle สัญญาณทุกครั้งที่มีการส่งข้อมูลดังนั้นจากภาพสัญญาณเอาต์พุตที่ได้ การส่งข้อมูลแต่ละครั้งจะเกิดขึ้นทุกๆ 52ms ถึง 54ms ซึ่งใกล้เคียงกับขีดจำกัดที่เว็บ Plot.ly สามารถรับข้อมูลได้คือทุกๆ 50ms
  • VDO ผลการทดลอง

 สรุปผลการทดลอง
        สำหรับการทดลองพบว่าการวัดแรงดันจะความใกล้เคียงระหว่างค่าที่วัดได้จากมัลติมิเตอร์ และค่าที่วัดได้จาก ADC ของบอร์ด STM32F3Discovery แต่สำหรับวัดกระแสจะความแตกต่างอยู่พอสมควรระหว่างค่าที่วัดได้จากมัลติมิเตอร์และค่าที่วัดได้จาก ACS712 ซึ่งจากภาพของกราฟที่ได้พบว่ากราฟของกระแสที่วัดได้จะมีการแกว่งขึ้นลงอยู่ตลอดเวลา และกราฟของแรงดันจะลักษณะคงที่ และสำหรับการส่งข้อมูลไปยังเว็บ Plot.ly อาจจะมีความไม่ต่อเนื่องเพราะขึ้นอยู่กับความเร็วอินเตอร์เน็ต แต่สำหรับการส่งข้อมูลจากบอร์ด STM32F3Discovery มายังคอมพิวเตอร์นั้นสามารถส่งข้อมูลได้ต่อเนื่องและมีความถี่ค่อนข้างคงที่

>>> ดาวน์โหลดรายงานสำหรับ Mini-Project ที่นี่ <<< 

ไม่มีความคิดเห็น:

แสดงความคิดเห็น