จัดทำโดย
นายธัชกร คุ้นเคย รหัสนักศึกษา
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. การแบ่งงานในกลุ่ม
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) อ่านบทความ
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
- โมดูล Ethernet ENC28J60
สำหรับโมดูล 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
ซึ่งมีโค้ดดังต่อไปนี้
4. ทำการเปิดไฟล์ index.html เพื่อแสดงผลหน้าเว็บ โดยมีโค้ด HTML ดังต่อไปนี้
สำหรับหน้าเว็บที่แสดงผลจะมีการจัดรูปแบบการแสดงผลให้สวยงามด้วยโค้ด CSS ซึ่งมีโค้ดดังต่อไปนี้
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 |
- VDO ผลการทดลอง
สรุปผลการทดลอง
สำหรับการทดลองพบว่าการวัดแรงดันจะความใกล้เคียงระหว่างค่าที่วัดได้จากมัลติมิเตอร์ และค่าที่วัดได้จาก ADC ของบอร์ด STM32F3Discovery แต่สำหรับวัดกระแสจะความแตกต่างอยู่พอสมควรระหว่างค่าที่วัดได้จากมัลติมิเตอร์และค่าที่วัดได้จาก ACS712 ซึ่งจากภาพของกราฟที่ได้พบว่ากราฟของกระแสที่วัดได้จะมีการแกว่งขึ้นลงอยู่ตลอดเวลา และกราฟของแรงดันจะลักษณะคงที่ และสำหรับการส่งข้อมูลไปยังเว็บ Plot.ly อาจจะมีความไม่ต่อเนื่องเพราะขึ้นอยู่กับความเร็วอินเตอร์เน็ต แต่สำหรับการส่งข้อมูลจากบอร์ด STM32F3Discovery มายังคอมพิวเตอร์นั้นสามารถส่งข้อมูลได้ต่อเนื่องและมีความถี่ค่อนข้างคงที่
>>> ดาวน์โหลดรายงานสำหรับ Mini-Project ที่นี่ <<<
>>> ดาวน์โหลดรายงานสำหรับ Mini-Project ที่นี่ <<<
















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