Define Array in C

ref: https://stackoverflow.com/questions/9846920/define-array-in-c
Contoh kasusny adalah saya ingin membuat/mendefinisikan data array yang bisa saya gunakan dan mengambil dari sebuah header file .h pada sebuah sistem embedded???

Jangan simpan data di header file. Simpan data di file C atau C++ biasa. Kemudian gunakan header file untuk mengakses data.
sebagai contoh, pada sebuah file images.c :

#include "images.h"
const byte numbers1[MAX_NUMBERS1] = { ... };
byte numbers2[MAX_NUMBERS2];       // will be initialsied to 0

kemudian pada file images.h :

#ifndef _IMAGES_H_
#define _IMAGES_H_

typedef unsigned char byte;
#define MAX_NUMBERS1 (450)
        // different constants in case you change something        
#define MAX_NUMBERS2 (450)      
       // even better if you can do const static int MAX_NUMBERS1=450; 
       // but depends on the compiler
extern const byte numbers1[MAX_NUMBERS1] = { ... };
extern byte numbers2[MAX_NUMBERS2];       // will be initialised to 0

#endif

Maka dengan demikian semua file .c pada program dapat mengakses variable array tersebut. Biasanya menyimpan definition dari sebuah variable di header file adalah ide yang buruk.
Sebuah deklarasi variable, misal extern byte numbers2[MAX_NUMBERS2]; memberitahukan compiler C bahwa ada sebuah variable array numbers2 tertulis di program. Jika linker tidak mendapati definisi tersebut maka akan menyebabkan error karena memory tidak akan mengalokasikan slot untuk variable tersebut.
Definisi dari sebuah variable (tanpa extern), misal byte numbers2[MAX_NUMBER2]; akan memberi tahu compiler C bahwa ada variable array dengan nama numbers2 dan memory harus mengalokasikan slot data pada object code dari source file.
Slot memory untuk numbers2 tidak akan dialokasikan oleh compiler C ketika dia melihat ada deklarasi (didahului oleh extern), dialokasikan bila melihat actual definition (tanpa extern).
Jadi, jika kita menggunakan actual definition dari variable apa saja di header file, dan memanggilnya di di banyak file .c, compiler C akan mengalokasikan memory untuk variable tersebut juga lebih dari satu kali. Kemudian linker akan mengeluarkan error (biasanya error multiple definitions of the same name).
Biasanya ada masalah yang sering tidak kita sadari. Ketika kita membuat program pertama kali, dan header file digunakan hanya pada satu program, program bisa dicompile tanpa error. Namun di lain waktu, jika ada program kedua yang memanggil header file tersebut (bisa saja seiring berjalannya waktu kita membagi program utama kita menjadi dua .c yang berbeda), linker akan mengeluarkan error ‘multiple definitions error’. Hal ini akan sangat membingungkan karena yang kita compile secara algoritma tidak ada perubahan.
Kesimpulan: Janga pernah mengalokasikan memory untuk sebuah variable dengan menyimpannya di header file. Yang disimpan di header file cukup variable definition saja.

Advertisements

IOT MQTT: Simple Node-Red + Raspberry Pi

Berikut adalah project sederhana untuk membuat iot dengan menggunakan node red dashboard untuk memonitor push button & mengontrol LED. Node-Red diinstall pada PC dan bertindak sebagai broker. Sedangkan raspberry pi sebagai client. Push button pada GPIO 21 & LED pada GPIO 22.
Skenarionya, HP Android akan mengontrol raspberry pi dengan mengakses halaman web dari node-red.
Langkah pertama adalah install node-red di PC.

Kemudian check npm dan node command.

Kemudian install node-red

kemudian jalankan node-red

Sekarang coba untuk akses dari web browser.

Kemudian kita akan install node-red dashboard dengan cara klik menu dan pilih manage pallete

Lalu install node-red dashboard.

Kemudian cobalah untuk membuat flow sebagai berikut lalu klik deploy mengaktifkan.

Gunakan menu debug untuk melihat message.

Setelah terlihat icon connected pada blok mqtt maka komunikasi sudah siap. Klik tanda panah pada menu dashboard untuk membukan web dashboard.

Install mqqt client pada raspberry pi.

https://eclipse.org/paho/clients/python/

Lalu buat file python .py dan ¬¬¬¬kita jalankan kode berikut pada raspberry pi.

import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
import time

def on_connect(client, userdata,flags, rc):
	if rc==0:
		print("connected OK")
	else:
		print("Bad connection Returned code=",rc)

def on_message(client, userdata, message):
	print("message received" ,str(message.payload.decode("utf-8")))
	print("message topic=",message.topic)
	print("message qos=",message.qos)
	print("message retain flag=",message.retain)
	if (str(message.payload.decode("utf-8")) == "true"):
		GPIO.output(22, GPIO.HIGH)
	else:
		GPIO.output(22, GPIO.LOW)		

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(21, GPIO.IN)
GPIO.setup(22, GPIO.OUT)

broker="10.20.56.34"
client=mqtt.Client("telu")
client.on_connect = on_connect
client.on_message = on_message
print("Connecting to broker",broker)
client.loop_start()
client.connect(broker,1883,60)
bool2send = False
while True:
	client.subscribe("edg/SlideRaspi")
	if (GPIO.input(21) == False):
		bool2send = True
	else:
		bool2send = False
	client.publish("edg/StatButton",str(bool2send))
	print("publish" ,str(bool2send))
	time.sleep(1)
client.loop_stop()
client.disconnect()

lalu jalankan pada raspberry pi dengan perintah sudo python [nama file].py
Bisa juga diatur agan program tersebut diset sebagai program autorun agar dijalankan secara otomatis saat raspberry pi pertama dinyalakan.
Setelah node-red pada PC dijalankan dan program client pada raspberry dijalankan, maka raspberry pi sudah bisa dikontrol lewat Android.


——————————————————
ref:
youtube.com/watch?v=O-FDqkhCryA
youtube.com/watch?v=xWzz8wGgdkU
https://sivatechworld.wordpress.com/2015/06/11/step-by-step-installing-and-configuring-mosquitto-with-windows-7/
https://developer.ibm.com/recipes/tutorials/generating-random-numbers-in-nodered/
https://eclipse.org/paho/clients/python/
youtube.com/watch?v=Pb3FLznsdwI
https://raspberrypi.stackexchange.com/questions/51621/installing-all-python-modules
https://learn.adafruit.com/playing-sounds-and-using-buttons-with-raspberry-pi/install-python-module-rpi-dot-gpio

Speech Recognition: CMUSphinx + Raspberry Pi

Beberapa waktu lalu saya penasaran dengan aplikasi speech recognition. Setelah bertanya pada teman saya disarankan untuk menggunakan engine dari CMUSphix. Kelengkapan alatnya adalah raspberry pi + usb microphone + 2 buah LED sebagai device yang akan kita kontrol menggunakan suara.

Langsung saja kita install aplikasi yang dibutuhkan oleh raspbian. Silahkan buka link berikut
https://wolfpaulus.com/embedded/raspberrypi2-sr/
atau jalankan satu-persatu command di bawah ini.

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install bison
sudo apt-get install libasound2-dev
sudo apt-get install swig
sudo apt-get install python-dev
sudo apt-get install mplayer
sudo reboot

lalu mari kita cek apakah microphone dan speaker bekerja dengan baik.

arecord -D plughw:0,0 -f cd ./test.wav

gunakan ctrl+c untuk berhenti merekam. Lalu mainkan hasil rekaman kita.

aplay ./test.wav

setelah itu, kita install sphinxbase.

cd ~/
wget http://sourceforge.net/projects/cmusphinx/files/sphinxbase/5prealpha/sphinxbase-5prealpha.tar.gz
tar -zxvf ./sphinxbase-5prealpha.tar.gz
cd ./sphinxbase-5prealpha
./configure --enable-fixed
make clean all
make check
sudo make install

setelah itu, install pocketsphinx

cd ~/
wget http://sourceforge.net/projects/cmusphinx/files/pocketsphinx/5prealpha/pocketsphinx-5prealpha.tar.gz
tar -zxvf pocketsphinx-5prealpha.tar.gz
cd ./pocketsphinx-5prealpha
./configure
make clean all
make check
sudo make install

Kemudian mari kita buat language model dan dictionary yang berformat .lm dan .dic
Buatlah sebuah text file kemudian isikan kata-kata yang akan dikenali oleh raspbery pi.

Hello Pixel
Red On
Red Off
Blue On
Blue Off
All On
All Off
Shutdown Now

save file tersebut dan berinama apa saja. Lalu buka link berikut. http://www.speech.cs.cmu.edu/tools/lmtool-new.html untuk meng-generate .lm dan .dic

Download .lm dan .dic, lalu buat direktori project kita. Misal saya gunakan nama folder MySphinx di directory /home/pi/MySphinx.

Setelah itu buka console kembali dan kita test pocketsphinx dan language model yang sudah kita generate. Jangan lupa ketikan nama .lm dan .dic yang telah kita donwload tadi mempunyai nama yang sama dengan command berikut dan kode di bawah nanti.

cd ~/
export LD_LIBRARY_PATH=/usr/local/lib
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
pocketsphinx_continuous -hmm /usr/local/share/pocketsphinx/model/en-us/en-us -lm /home/pi/MySphinx/4979.lm -dict /home/pi/MySphinx/4979.dic -samprate 16000/8000/48000 -inmic yes –adcdev plughw:1,0

-adcdev plughw:1,0 merupakan perintah untuk memilih device ID dari microphone. Cek dengan command

cat /proc/asound/cards

Hasilnya adalah.

0 [ALSA ]: bcm2835 - bcm2835 ALSA
bcm2835 ALSA
1 [AK5370 ]: USB-Audio - AK5370
AKM AK5370 at usb-bcm2708_usb-1.2, full speed

Setelah pocketsphinx berhasil maka mari kita buat custom project kita sendiri. Skenarionya adalah, ketika program dijalankan maka akan memainkan musik piano, lalu raspberry pi akan mengucapkan hello sir. Kemudian barulah raspbery pi memulai voice recognition dan akan menjalankan perintah yang kita berikan, yaitu menghidupkan/mematikan LED dan auto shutdown.
Buka console kembali. Kita install terlebih dahulu espeak.

sudo apt-get install espeak

untuk mengetesnya ketik command.

espeak "hello"

maka dari raspberry pi akan keluar suara hello.
Setelah itu, kita donwload file piano.wav yang akan kita gunakan sebagai musik pembuka.

cd /home/pi/MySphinx
wget http://www.kozco.com/tech/piano2.wav

setelah itu, kita coba cek mainkan file tersebut dengan ketikan.

aplay piano2.wav

Kemudian, setelah file dan aplikasi yang kita butuhkan sudah lengkap. Kita buat file test3.c lalu masukan kode berikut.

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <wiringPi.h>

#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#else
#include <sys/select.h>
#endif

#include <sphinxbase/err.h>
#include <sphinxbase/ad.h>

#include "pocketsphinx.h"

#define LED_RED	21
#define LED_BLUE	22

static ps_decoder_t *ps;
static cmd_ln_t *config;

/* Sleep for specified msec */
static void
sleep_msec(int32 ms)
{
#if (defined(_WIN32) && !defined(GNUWINCE)) || defined(_WIN32_WCE)
    Sleep(ms);
#else
    /* ------------------- Unix ------------------ */
    struct timeval tmo;

    tmo.tv_sec = 0;
    tmo.tv_usec = ms * 1000;

    select(0, NULL, NULL, NULL, &tmo);
#endif
}

/*
 * Main utterance processing loop:
 *     for (;;) {
 *        start utterance and wait for speech to process
 *        decoding till end-of-utterance silence will be detected
 *        print utterance result;
 *     }
 */
static void
recognize_from_microphone()
{
    ad_rec_t *ad;
    int16 adbuf[2048];
    uint8 utt_started, in_speech;
    int32 k;
    char const *hyp;

    if ((ad = ad_open_dev("plughw:0,0",16000)) == NULL)
        E_FATAL("Failed to open audio device\n");
    if (ad_start_rec(ad) < 0)
        E_FATAL("Failed to start recording\n");

    if (ps_start_utt(ps) < 0)
        E_FATAL("Failed to start utterance\n");
    utt_started = FALSE;
    E_INFO("Ready....\n");

    for (;;) {
        if ((k = ad_read(ad, adbuf, 2048)) < 0)
            E_FATAL("Failed to read audio\n");
        ps_process_raw(ps, adbuf, k, FALSE, FALSE);
        in_speech = ps_get_in_speech(ps);
        if (in_speech && !utt_started) {
            utt_started = TRUE;
            E_INFO("Listening...\n");
        }
        if (!in_speech && utt_started) {
            /* speech -> silence transition, time to start new utterance  */
            ps_end_utt(ps);
            hyp = ps_get_hyp(ps, NULL );
            if (hyp != NULL) {
		if(	strcmp(hyp,"HELLO PIXEL") == 0)
		{
			system("espeak 'hello, what can i do for you, sir'");
			printf("%s\n", hyp);
		}else if(strcmp(hyp,"RED ON") == 0)
		{
			system("espeak 'red, on'");
			printf("%s\n", hyp);
			digitalWrite(LED_RED , HIGH);
		}else if(strcmp(hyp,"RED OFF") == 0)
		{
			system("espeak 'red, off'");
			printf("%s\n", hyp);
			digitalWrite(LED_RED , OFF);
		}else if(strcmp(hyp,"BLUE ON") == 0)
		{
			system("espeak 'blue, on'");
			printf("%s\n", hyp);
			digitalWrite(LED_BLUE , HIGH);
		}else if(strcmp(hyp,"BLUE OFF") == 0)
		{
			system("espeak 'blue, off'");
			printf("%s\n", hyp);
			digitalWrite(LED_BLUE , OFF);
		}else if(strcmp(hyp,"ALL ON") == 0)
		{
			system("espeak 'all, on'");
			printf("%s\n", hyp);
			digitalWrite(LED_RED ,  HIGH);
			digitalWrite(LED_BLUE , HIGH);
		}else if(strcmp(hyp,"ALL OFF") == 0)
		{
			system("espeak 'all, off'");
			printf("%s\n", hyp);
			digitalWrite(LED_RED , LOW);
			digitalWrite(LED_BLUE , LOW);
		}else if(strcmp(hyp,"SHUTDOWN NOW") == 0)
		{
			printf("%s\n", hyp);
			system("aplay -D plughw:CARD=ALSA /home/pi/MySphinx/piano2.wav && shutdown now");
		}else
		{
			printf("Thinking....%s\n", hyp);
		}
                fflush(stdout);
            }

            if (ps_start_utt(ps) < 0)
                E_FATAL("Failed to start utterance\n");
            utt_started = FALSE;
            E_INFO("Ready....\n");
        }
        sleep_msec(100);
    }
    ad_close(ad);
}

int
main(int argc, char *argv[])
{
    char const *cfg;

    config = cmd_ln_init(	NULL, ps_args(), TRUE,
				"-hmm", "/usr/local/share/pocketsphinx/model/en-us/en-us",
				"-lm",  "/home/pi/MySphinx/4979.lm",
				"-dict","/home/pi/MySphinx/4979.dic",
				"-samprate","16000/8000/48000",
				NULL);

    if(config == NULL){
	fprintf(stderr, "Failed to create object, see long for details\n");
	return -1;
    }

    ps = ps_init(config);
    if (ps == NULL) {
        fprintf(stderr, "Failed to create recognizer, see long for details\n");
	return -1;
    }

    E_INFO("%s COMPILED ON: %s, AT: %s\n\n", argv[0], __DATE__, __TIME__);
    
	wiringPiSetupGpio();
	pinMode(LED_RED,  OUTPUT);
	pinMode(LED_BLUE, OUTPUT);
	
    system("aplay -D plughw:CARD=ALSA /home/pi/MySphinx/piano2.wav && espeak 'Hello, Sir!' ");
	
	digitalWrite(LED_RED , HIGH);
	digitalWrite(LED_BLUE, HIGH);
	delay(500);
	digitalWrite(LED_RED , LOW);
	digitalWrite(LED_BLUE, LOW);
	
    recognize_from_microphone();
    
    ps_free(ps);
    cmd_ln_free_r(config);

    return 0;
}

Setelah itu kita kembali ke console terminal dan compile test3.c yang sudah kita buat. Kita masuk dulu ke directory MySphinx

cd /home/pi/MySphinx
gcc -o test3 test3.c -DMODELDIR=\"`pkg-config --variable=modeldir pocketsphinx`\" `pkg-config --cflags --libs pocketsphinx sphinxbase` -lwiringPi

Setelah itu kita jalankan dengan

sudo ./test3

Selesai.
Jika ingin dijalankan autorun maka tambahkan

sudo /home/pi/MySphinx/test3

di bagian terakhir dari /home/pi/.bashrc. Buka file tersebut dengan command

sudo nano /home/pi/.bashrc

agar raspberry pi dijalankan tanpa Desktop GUI lakukan pengaturan dengan command

sudo raspi-config

untuk mengecek parameter apa saja yang bisa dipakai pada pocketsphinx, ketikan saja pocketsphinx_continuous.

_______________________________________________________________________
referensi:
https://www.raspberrypi.org/forums/viewtopic.php?f=32&t=126436
https://wolfpaulus.com/embedded/raspberrypi2-sr/
http://www.penguintutor.com/linux/rpi-pixel-virtualbox
https://www.raspberrypi.org/forums/viewtopic.php?t=85627&p=604943
https://www.dexterindustries.com/howto/run-a-program-on-your-raspberry-pi-at-startup/
http://people.csail.mit.edu/hubert/pyaudio/#downloads
http://blog.justsophie.com/python-speech-to-text-with-pocketsphinx/
http://depado.markdownblog.com/2015-05-13-tutorial-on-pocketsphinx-with-python-3-4
https://cmusphinx.github.io/wiki/tutorialpocketsphinx/
https://www.dexterindustries.com/howto/make-your-raspberry-pi-speak/
https://www.howtogeek.com/269509/how-to-run-two-or-more-terminal-commands-at-once-in-linux/
http://mailman.alsa-project.org/pipermail/alsa-devel/2014-May/077142.html
https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=95724
youtube.com/watch?v=J6KsTz6hjfU

STM32F4 Discovery + STM32CubeMX + Keil: RTOS

Biasanya RTOS dipakai ketika aplikasi yang dibuat sudah mulai kompleks. Akan tetapi, pada postingan ini saya hanya mencoba dengan aplikasi push button dan led saja. Skenarionya adalah membuat 4 task.
Task 1 Fast blinking LED1 dengan delay 300ms
Task2 Slow blinking LED2 dengan delay 3000ms
Task3 read push button
Task4 merespon push button dengan LED3 dan LED4.
Buka STM32CubeMX dan buat New Project. Atur Pin configuration.

Enable FreeRTOS.

Pada tab configuration klik FreeRTOS

Buat task baru sebagai berikut.

Setelah itu klik generate source code. Berinama project dan setting toolchain MDK-ARM V5 lalu Klik OK dan Open Project. Buka main.c
Tambahkan variable counter dan statusLED sebagai berikut.

Lalu pada task yang sudah dibuat, kita tambahkan kode berikut.

Build project dan download program.
Berikut full code main.c

/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#include "cmsis_os.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/
osThreadId defaultTaskHandle;
osThreadId fastLEDHandle;
osThreadId slowLEDHandle;
osThreadId pushButtonHandle;
osThreadId restLEDHandle;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t counter = 0;
GPIO_PinState statusLED;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
void StartDefaultTask(void const * argument);
void StartFastLED(void const * argument);
void StartSlowLED(void const * argument);
void StartPushButton(void const * argument);
void StartRestLED(void const * argument);

/* 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();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* definition and creation of fastLED */
  osThreadDef(fastLED, StartFastLED, osPriorityNormal, 0, 128);
  fastLEDHandle = osThreadCreate(osThread(fastLED), NULL);

  /* definition and creation of slowLED */
  osThreadDef(slowLED, StartSlowLED, osPriorityNormal, 0, 128);
  slowLEDHandle = osThreadCreate(osThread(slowLED), NULL);

  /* definition and creation of pushButton */
  osThreadDef(pushButton, StartPushButton, osPriorityNormal, 0, 128);
  pushButtonHandle = osThreadCreate(osThread(pushButton), NULL);

  /* definition and creation of restLED */
  osThreadDef(restLED, StartRestLED, osPriorityNormal, 0, 128);
  restLEDHandle = osThreadCreate(osThread(restLED), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */
 

  /* Start scheduler */
  osKernelStart();
  
  /* We should never get here as control is now taken by the scheduler */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage 
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0);
}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);

  /*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 : PD12 PD13 PD14 PD15 */
  GPIO_InitStruct.Pin = 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_FREQ_LOW;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{

  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END 5 */ 
}

/* StartFastLED function */
void StartFastLED(void const * argument)
{
  /* USER CODE BEGIN StartFastLED */
  /* Infinite loop */
  for(;;)
  {
	HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
    osDelay(300);
  }
  /* USER CODE END StartFastLED */
}

/* StartSlowLED function */
void StartSlowLED(void const * argument)
{
  /* USER CODE BEGIN StartSlowLED */
  /* Infinite loop */
  for(;;)
  {
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13);
	osDelay(3000);
  }
  /* USER CODE END StartSlowLED */
}

/* StartPushButton function */
void StartPushButton(void const * argument)
{
  /* USER CODE BEGIN StartPushButton */
  /* Infinite loop */
  for(;;)
  {
	if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0))
	{
		while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0));
		counter++;
	}
    osDelay(1);
  }
  /* USER CODE END StartPushButton */
}

/* StartRestLED function */
void StartRestLED(void const * argument)
{
  /* USER CODE BEGIN StartRestLED */
  /* Infinite loop */
  for(;;)
  {
	if(counter == 0)
	{
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
	}
	else if(counter == 1)
	{
		HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_14);
		HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_15);
		HAL_Delay(1000);
	}
	else if(counter == 2)
	{
		statusLED = ~statusLED;
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, ~statusLED);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, statusLED);
		HAL_Delay(500);
	}
	else 
	{
		counter = 0;
	}
    osDelay(1);
  }
  /* USER CODE END StartRestLED */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler */
  /* User can add his own implementation to report the HAL error return state */
  while(1) 
  {
  }
  /* USER CODE END Error_Handler */ 
}

#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

/**
  * @}
  */ 

/**
  * @}
*/ 

STM32F4 Discovery + STM32CubeMX + Keil: Accelerometer

Pada kesempatan kali ini kita akan memcoba mengakses data dari sensor accelerometer dengan koneksi SPI dan menampilkan hasil pengukuran pada LED.


Berikut alamat register dari LIS3DSH, sensor accelerometer yang terdapat pada STM32F4 Discovery.

Buka aplikasi STM32CubeMX. Lalu buat New Project

Pilih tipe mikrokontroller sesuai dengan tipe STM32F4 Discovery yaitu STM32F407VG

Lakukan setting pada pin yang akan kita gunakan.

Pada tab configuration lakukan pengaturan sebagai berikut.

Setelah itu klik generate source code. Berinama project dan setting toolchain MDK-ARM V5 lalu Klik OK dan Open Project.
Buka main.c

int main(void)
{

  /* USER CODE BEGIN 1 */
	uint8_t address, data, x_accel, y_accel, i;
  /* 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_SPI1_Init();

  /* USER CODE BEGIN 2 */
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
	address = 0x20;
	HAL_SPI_Transmit(&hspi1, &address, 1, 50);
	data = 0x67;
	HAL_SPI_Transmit(&hspi1, &data, 1, 50);
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
		
	//Blinking LED sebagai indikator siap untuk read accelerometer
	for(i=0;i<4;i++)
	{
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
		HAL_Delay(500);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
		HAL_Delay(500);
	}
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
		/* USER CODE BEGIN 3 */
	
		//----------------------X AXIS---------------------------
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
		address = 0x29 + 0x80;
		HAL_SPI_Transmit(&hspi1, &address, 1, 50);
		HAL_SPI_Receive(&hspi1, &x_accel, 1, 50);
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
  	if((x_accel > 10)&&(x_accel < 127))
		{
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
		}
		else if((x_accel < 245)&&(x_accel > 127))
		{
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
		}
		//---------------------Y AXIS----------------------------
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
		address = 0x2B + 0x80;
		HAL_SPI_Transmit(&hspi1, &address, 1, 50);
		HAL_SPI_Receive(&hspi1, &y_accel, 1, 50);
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
  
		if((y_accel > 10)&&(y_accel < 127))
		{
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
		}
		else if((y_accel < 245)&&(y_accel > 127))
		{
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
		}
  }
  /* USER CODE END 3 */
}

_______________________________________________________________
referensi: youtube.com/channel/UC-CuJ6qKst9-8Z-EXjoYK3Q/videos

STM32F4 Discovery + STM32CubeMX + Keil: UART Interrupt

Buka aplikasi STM32CubeMX. Lalu buat New Project

Pilih tipe mikrokontroller sesuai dengan tipe STM32F4 Discovery yaitu STM32F407VG

Lakukan setting pada pin yang akan kita gunakan.

Pada tab Configuration klik USART1 dan lakukan pengaturan sebagai berikut.

Setelah itu aktifkan interrupt uart

Setelah itu klik generate source code. Berinama project dan setting toolchain MDK-ARM V5 lalu Klik OK dan Open Project.
Buka main.c
Pada main.c aktifkan uart dengan perintah enable.

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_USART1_UART_Init();

  /* USER CODE BEGIN 2 */
	__HAL_UART_ENABLE_IT(&amp;huart1, UART_IT_RXNE);
	__HAL_UART_ENABLE_IT(&amp;huart1, UART_IT_TC);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
   while (1)
  {
		/* USER CODE END WHILE */

		/* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

Setelah itu kita buat variable global sebagai berikut.

Buka stm32f4xx_it.c untuk mengakses Interrupt Service Routine

Pada file stm32f4xx_it.c buat variable global yang akan diakses dari main.c dengan tambahkan extern.

Pada fungsi dibawah ini ketikan perintah transmit dan receive sebagai berikut.


_______________________________________________________________
referensi: youtube.com/channel/UC-CuJ6qKst9-8Z-EXjoYK3Q/videos

STM32F4 Discovery + STM32CubeMX + Keil: UART

Buka aplikasi STM32CubeMX. Lalu buat New Project

Pilih tipe mikrokontroller sesuai dengan tipe STM32F4 Discovery yaitu STM32F407VG

Lakukan setting pada pin yang akan kita gunakan.

Pada tab Configuration klik USART1 dan lakukan pengaturan sebagai berikut.

Setelah itu klik generate source code. Berinama project dan setting toolchain MDK-ARM V5 lalu Klik OK dan Open Project.
Buka main.c

int main(void)
{

  /* USER CODE BEGIN 1 */
	char myDataTx[16] = "hello world!";
  char myDataRx[16];
	/* 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_USART1_UART_Init();

  /* USER CODE BEGIN 2 */
	HAL_UART_Transmit(&huart1, (uint8_t *)myDataTx, 16, 50);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		/* USER CODE END WHILE */
		HAL_UART_Receive(&huart1, (uint8_t *)myDataRx, 16, 50);
		/* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

}

_______________________________________________________________
referensi: youtube.com/channel/UC-CuJ6qKst9-8Z-EXjoYK3Q/videos

STM32F4 Discovery + STM32CubeMX + Keil: PWM

Buka aplikasi STM32CubeMX. Lalu buat New Project

Pilih tipe mikrokontroller sesuai dengan tipe STM32F4 Discovery yaitu STM32F407VG

Lakukan setting pada pin yang akan kita gunakan.

Kemudian pada tab configuration klik TIM1 dan lakukan pengaturan sebagai berikut.

Setelah itu klik generate source code. Berinama project dan setting toolchain MDK-ARM V5 lalu Klik OK dan Open Project.
Buka main.c

int main(void)
{

  /* USER CODE BEGIN 1 */
	uint16_t 	dutyCycle1 = 10, 
						dutyCycle2 = 90, 
						dutyCycle3 = 10, 
						dutyCycle4 = 90;
  /* 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_TIM1_Init();

  /* USER CODE BEGIN 2 */
	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
	htim1.Instance->CCR1 = dutyCycle1;
	dutyCycle1 += 10;
	if(dutyCycle1 > 90)dutyCycle1 = 10;
		
	htim1.Instance->CCR2 = dutyCycle2;
	dutyCycle2 -= 10;
	if(dutyCycle2 < 10)dutyCycle2 = 90;
		
	htim1.Instance->CCR3 = dutyCycle3;
	dutyCycle3 += 10;
	if(dutyCycle3 > 90)dutyCycle3 = 10;
		
	htim1.Instance->CCR4 = dutyCycle4;
	dutyCycle4 -= 10;
	if(dutyCycle4 < 10)dutyCycle4 = 90;
		
	HAL_Delay(1);	
  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

Berikut hasil signal PWM yang tergenerate.

_______________________________________________________________
referensi: youtube.com/channel/UC-CuJ6qKst9-8Z-EXjoYK3Q/videos

STM32F4 Discovery + STM32CubeMX + Keil: DAC

Buka aplikasi STM32CubeMX. Lalu buat New Project

Pilih tipe mikrokontroller sesuai dengan tipe STM32F4 Discovery yaitu STM32F407VG

Lakukan setting pada pin yang akan kita gunakan.

Setelah itu generate source code, beri nama project dan setting toolchain MDK-ARM V5. Kemudian open project. Buka main.c


int main(void)
{

  /* USER CODE BEGIN 1 */
	uint32_t value = 100;
  /* 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_DAC_Init();

  /* USER CODE BEGIN 2 */
	HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
	/* USER CODE BEGIN 3 */
	HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_8B_R, value);
	value+=15;	
  if(value>255)value=100;
	HAL_Delay(500);
  }
  /* USER CODE END 3 */

}

_______________________________________________________________
referensi: youtube.com/channel/UC-CuJ6qKst9-8Z-EXjoYK3Q/videos

STM32F4 Discovery + STM32CubeMX + Keil: ADC Continuous Conversion

Berikut spesifikasi ADC dari STM32.
http://embedded-lab.com/blog/stm32-adc-2/

Buka aplikasi STM32CubeMX lalu buat project baru dan buat pengaturan sebagai berikut. Kita pilih ADC2_IN2.

Pada tab Configure klik ADC2.

Lakukan pengaturan sebagai berikut.

Klik OK lalu generate source code. Jangan lupa beri nama project dan setting toolchain MDK-ARM V5. Setelah itu, open project. Buka main.c.
Berikut kode pada main.c

int main(void)
{

  /* USER CODE BEGIN 1 */
	uint32_t adcValue; 
  /* 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_ADC2_Init();

  /* USER CODE BEGIN 2 */
	HAL_ADC_Start(&hadc2);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
	
  /* USER CODE BEGIN 3 */
	adcValue = HAL_ADC_GetValue(&hadc2);
  }
  /* USER CODE END 3 */

}

_______________________________________________________________
referensi: youtube.com/channel/UC-CuJ6qKst9-8Z-EXjoYK3Q/videos