Zint is a cross-platform open source barcode generating library which can be found at
https://www.zint.org.uk/.
You can get zint from the following github repository.
https://github.com/woo-j/zint.
Showing posts with label C++. Show all posts
Showing posts with label C++. Show all posts
Wednesday, July 6, 2022
Friday, September 17, 2021
V4L2 Capturing as Bitmap Image
V4L2 (Video for Linux 2) consists of drivers and API for video capturing on Linux
[1].
In this article, we will discuss about using the library and analysis of video capture example.
There are utilities for controlling media devices on Linux called v4l-utils
[2].
We will explore about using and testing webcam with them also.
Friday, January 10, 2020
Getting Started with FRDM-K82F
FRDM-K82F
is a low cost development platform using MK82FN256VLL15 microcontroller.
When I started using the board according to its getting started guide at
Get Started with the FRDM-K82F [NXP16],
I found out that its out-of-box demo is not running on my version of FRDM-K82F board. The insturctions on that page are also out of date. And, I could not get it worked.
After spending my time testing, browing the Internet, and experimenting, I found out that the following things might be necessary, in a brief, to make the board worked.
Get Started with the FRDM-K82F [NXP16],
I found out that its out-of-box demo is not running on my version of FRDM-K82F board. The insturctions on that page are also out of date. And, I could not get it worked.
After spending my time testing, browing the Internet, and experimenting, I found out that the following things might be necessary, in a brief, to make the board worked.
- Debug adapter - update it
- IDE - use MCUXpresso instead of Kinetis Studio
- SDK - use MCUXpresso SDK Builder (make sure to 'drag and drop')
- Flash - unlock the MCU's flash if required
Saturday, August 11, 2018
DIY Programmable Function Generator Using Arduino Uno
It is possible to use Arduino Uno as a function generator to produce low frequency waveform.
The advantage of the approach is the possibility of producing customized, complex, time varying waveform.
On the down side, it cannot produce waveform with very high frequencies.
To get smoother waveform, the PWM output frequency of pin 3 of Arduino Uno is increased to approximately 8 kHz.
It is also possible to use DAC to achieve better results.
Tuesday, January 23, 2018
UDP/TCP Socket Programming with wxWidgets
Introduction
In this article, UDP and TCP socket programming using wxWidgets is discussed. For that wxWidgets needs to be installed in your machine. Installing wxWidgets on Windows and Linux platforms can be seen at the following link.Sockets are used to send and receive data on a network such as the Internet. Almost all modern operating systems support socket layer to transfer data using TCP or UDP. But programming sockets on different platforms usually involves platform specific tweaks. wxWidgets support socket classes which allow you to use sockets for transferring data without concerning about the platform. These classes can be used in various ways and some of them are discussed in the following sections.
Monday, November 20, 2017
OpenCV on Linux using g++, CMake, Qt, Code::Blocks
Introduction
To install OpenCV on your Linux machine, you need to have the following packages as prerequisites [Ope17g].- GCC 4.4.x or later
- CMake 2.6 or higher
- Git
- GTK+2.x or higher, including headers (libgtk2.0-dev)
- pkg-config
- Python 2.6 or later and Numpy 1.5 or later with developer packages (python-dev, python-numpy)
- ffmpeg or libav development packages: libavcodec-dev, libavformat-dev, libswscale-dev
- [optional] libtbb2 libtbb-dev
- [optional] libdc1394 2.x
- [optional] libjpeg-dev, libpng-dev, libtiff-dev, libjasper-dev, libdc1394-22-dev
Thursday, March 24, 2016
Gyroscope L3G4200D
L3G4200D is a MEMS ultra-stable three-axis digital output gyroscope made by STMicroelectronics. A L3G4200D Module in Aliexpress costs only about $3.
Wednesday, November 25, 2015
CC2531 Zigbee USB Dongle
In this article, we discuss about using CC2531 USB Evaluation Module Kit for wireless communication. At first, a zip file - CC USB Firmware Library and Examples, was downloaded from TI's website. After that, USB RF Modem Example in CC USB Software Examples User’s Guide was tested.
Labels:
2.4 GHz,
8051,
C,
C++,
CC2530,
Circuit,
Communication,
Electronics,
firmware,
Free Software,
Hardware,
IAR,
IEEE 802.15.4,
Microcontroller,
Robotics,
TI,
USB,
Wireless,
Zigbee
Tuesday, November 24, 2015
Wireless Communication using CC2530 Zigbee Wireless MCU
CC2530 is an system-on-chip (SoC) solution for IEEE 802.15.4 and Zigbee that combines RF transceiver and 8051 MCU. To develop a wireless module using it, we had bought a CC2530DK devolopment kit that consists of 2 CC2530EM Evaluation Modules, 2 SmartRF05EB Evaluation Boards, and a CC2531 USB Dongle. It cost about USD 400. At first, we installed SmartRF Studio which was available for free at TI's website.
Labels:
2.4 GHz,
8051,
C,
C++,
CC2530,
Circuit,
Communication,
Electronics,
firmware,
Free Software,
Hardware,
IAR,
IEEE 802.15.4,
Microcontroller,
Robotics,
TI,
Wireless,
Zigbee
Thursday, March 6, 2014
Reading Rotary Encoder Using Microcontroller
Rotary encoders are commonly used for measuring angular position or motion sensing.
An optical encoder has a disc with a pattern of cutouts. As the disc rotated, an LED light that shines on photo detector is turned on and off accordingly to produce a digital waveform.
Gray code is normally used in encoders instead of ordinary binary code to prevent glitches. In Gray code, the number of changing bits between successive numbers is only 1. The following table shows 2 bit Gray code from 0 to 3.
Gray code is normally used in encoders instead of ordinary binary code to prevent glitches. In Gray code, the number of changing bits between successive numbers is only 1. The following table shows 2 bit Gray code from 0 to 3.
Monday, July 8, 2013
CAN bus
CAN bus (controller area network) is a vehicle bus standard designed to allow microcontrollers and devices to communicate with each other. CAN bus is a message-based protocol, designed specifically for automotive applications but now also used in other areas such as aerospace, industrial automation and medical equipment.
The advantages of CAN bus compared to RS232 communication are as follows.
Sunday, January 13, 2013
Changing sampling rate using quadratic regression
I want to change sampling rate of a signal from 333Hz to 5000Hz. To get a smoother result, I have implemented second order hold system instead of popular zero order hold (ZOH) system. This approach can also be used for down sampling. Another possible application is to filter out noise without introducing phase delay. And it can be useful for real-time application.
Approach 1: Quadratic regression
Quadratic function is defined as
$$f=w_0+w_1 x + w_2 x^2$$
Then, cost function to be minimized is defined as
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-f_i)^2$$
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)^2$$
Optimal weights can be found by differentiating the cost function and setting them to zero.
$$\frac{\partial J(w)}{\partial w_0}=0$$
$$-\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)=0$$
$$w_0\sum_{i=1}^{n}1+w_1\sum_{i=1}^{n}x_i+w_2\sum_{i=1}^{n}x_i^2=\sum_{i=1}^{n}y_i$$
Similarly, differentiating with w1 and w2 gives,
$$w_0\sum_{i=1}^{n}x_i+w_1\sum_{i=1}^{n}x_i^2+w_2\sum_{i=1}^{n}x_i^3=\sum_{i=1}^{n}y_i x_i$$
$$w_0\sum_{i=1}^{n}x_i^2+w_1\sum_{i=1}^{n}x_i^3+w_2\sum_{i=1}^{n}x_i^4=\sum_{i=1}^{n}y_i x_i^2$$
When these three equations are written in matrix form.
$$ \begin{bmatrix} \sum_{i=1}^{n}1 & \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 \\ \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 \\ \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 & \sum_{i=1}^{n}x_i^4 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^{n}y_i \\ \sum_{i=1}^{n}y_i x_i \\ \sum_{i=1}^{n}y_i x_i^2 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$
Approach 2: Three equations
In our case, we can use only the last three points and we can get three equations from these three points.
$$y_1=w_0+w_1 x_1 + w_2 x_1^2$$
$$y_2=w_0+w_1 x_2 + w_2 x_2^2$$
$$y_3=w_0+w_1 x_3 + w_2 x_3^2$$
$$ \begin{bmatrix} 1 & x_1 & x_1^2 \\ 1 & x_2 & x_2^2 \\ 1 & x_3 & x_3^2 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$
Approach 3: Two equations
If we define x1=-1, x2=0, and x3=1, y2 is equal to w0. And,
$$y_1=y_2-w_1+ w_2$$
$$y_3=y_2+w_1+ w_2$$
$$ \begin{bmatrix} -1 & 1 \\ 1 & 1 \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
$$ \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} -0.5 & 0.5 \\ 0.5 & 0.5 \end{bmatrix} \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
Then, we have
$$w_0=y_2$$
$$w_1=-0.5(y_1-y_2)+0.5(y_3-y2)$$
$$w_2=0.5(y_1-y_2)+0.5(y_3-y2)$$
I have tested the above three approaches using MatLab and it is shown below.
Approach 1: Quadratic regression
Quadratic function is defined as
$$f=w_0+w_1 x + w_2 x^2$$
Then, cost function to be minimized is defined as
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-f_i)^2$$
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)^2$$
Optimal weights can be found by differentiating the cost function and setting them to zero.
$$\frac{\partial J(w)}{\partial w_0}=0$$
$$-\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)=0$$
$$w_0\sum_{i=1}^{n}1+w_1\sum_{i=1}^{n}x_i+w_2\sum_{i=1}^{n}x_i^2=\sum_{i=1}^{n}y_i$$
Similarly, differentiating with w1 and w2 gives,
$$w_0\sum_{i=1}^{n}x_i+w_1\sum_{i=1}^{n}x_i^2+w_2\sum_{i=1}^{n}x_i^3=\sum_{i=1}^{n}y_i x_i$$
$$w_0\sum_{i=1}^{n}x_i^2+w_1\sum_{i=1}^{n}x_i^3+w_2\sum_{i=1}^{n}x_i^4=\sum_{i=1}^{n}y_i x_i^2$$
When these three equations are written in matrix form.
$$ \begin{bmatrix} \sum_{i=1}^{n}1 & \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 \\ \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 \\ \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 & \sum_{i=1}^{n}x_i^4 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^{n}y_i \\ \sum_{i=1}^{n}y_i x_i \\ \sum_{i=1}^{n}y_i x_i^2 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$
Approach 2: Three equations
In our case, we can use only the last three points and we can get three equations from these three points.
$$y_1=w_0+w_1 x_1 + w_2 x_1^2$$
$$y_2=w_0+w_1 x_2 + w_2 x_2^2$$
$$y_3=w_0+w_1 x_3 + w_2 x_3^2$$
$$ \begin{bmatrix} 1 & x_1 & x_1^2 \\ 1 & x_2 & x_2^2 \\ 1 & x_3 & x_3^2 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$
Approach 3: Two equations
If we define x1=-1, x2=0, and x3=1, y2 is equal to w0. And,
$$y_1=y_2-w_1+ w_2$$
$$y_3=y_2+w_1+ w_2$$
$$ \begin{bmatrix} -1 & 1 \\ 1 & 1 \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
$$ \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} -0.5 & 0.5 \\ 0.5 & 0.5 \end{bmatrix} \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
Then, we have
$$w_0=y_2$$
$$w_1=-0.5(y_1-y_2)+0.5(y_3-y2)$$
$$w_2=0.5(y_1-y_2)+0.5(y_3-y2)$$
I have tested the above three approaches using MatLab and it is shown below.
%------------------------------------------------------------------------- clc; close all; clear all; %------------------------------------------------------------------------- % y= w0 + w1*x + w2* x^2; %------------------------------------------------------------------------- %Got x and y x=[-1 0 1]'; Wo=[4 3 2]'; y=Wo(1)+Wo(2)*x+Wo(3).*x.*x; %------------------------------------------------------------------------- %Approach 1 %Polynomial regression of order 2 %For n=3 S1=3; Sx=sum(x); Sx2=sum(x.*x); Sx3=sum(x.*x.*x); Sx4=sum(x.*x.*x.*x); Sy=sum(y); Syx=sum(y.*x); Syx2=sum(y.*x.*x); P=[S1 Sx Sx2; Sx Sx2 Sx3; Sx2 Sx3 Sx4]; B=[Sy Syx Syx2]'; %P1=P^(-1); W1=P\B %------------------------------------------------------------------------- %Approach 2 %Linear equations A=[1 x(1) x(1)*x(1);1 x(2) x(2)*x(2); 1 x(3) x(3)*x(3)]; W2=A\y %------------------------------------------------------------------------- %Approach 3 %Only 2 linear equations w0=y(2); w1=-0.5*( y(1)- y(2))+0.5*( y(3)- y(2)); w2=0.5*( y(1)- y(2))+0.5*(y(3)- y(2)); W3=[w0 w1 w2]' %-------------------------------------------------------------------------The following figure shows the result of using this method (blue color plot) compare to ordinary zero order hold (black color plot). This method gives much more smoother result but it should be noted that it introduces one sample delay. The implementation of this method in LabVIEW using C code is shown in the following figure. The first two approaches involve finding inverse of a 3x3 matrix and I have developed a C program as shown below.
#include#include main() { float M[3][3]={{3,0,2},{0,2,0},{2,0,2}}; //initialize a 3x3 matrix float N[3][3]={{0,0,0},{0,0,0},{0,0,0}}; //allocate for inverse int i,j; float d; //------------------------------------------------------------------------- N[0][0]=(M[1][1]*M[2][2]-M[2][1]*M[1][2]); N[1][0]=-(M[1][0]*M[2][2]-M[2][0]*M[1][2]); N[2][0]=(M[1][0]*M[2][1]-M[1][1]*M[2][0]); d=M[0][0]*N[0][0]+M[0][1]*N[1][0]+M[0][2]*N[2][0]; N[0][0]/=d; N[1][0]/=d; N[2][0]/=d; N[0][1]=-(M[0][1]*M[2][2]-M[0][2]*M[2][1])/d; N[1][1]=(M[0][0]*M[2][2]-M[0][2]*M[2][0])/d; N[2][1]=-(M[0][0]*M[2][1]-M[0][1]*M[2][0])/d; N[0][2]=(M[0][1]*M[1][2]-M[0][2]*M[1][1])/d; N[1][2]=-(M[0][0]*M[1][2]-M[0][2]*M[1][0])/d; N[2][2]=(M[0][0]*M[1][1]-M[0][1]*M[1][0])/d; //------------------------------------------------------------------------- //print 3x3 matrix for(i=0;i<3;i++) { for(j=0;j<3;j++) printf("%3.4f ",N[i][j]); printf("\n"); } getch(); return 0; }
Tuesday, May 3, 2011
Byte Stuffing
I occasionally need to write programs to send and receive data bytes from one device to another. That is why I arbitrarily choose a simple variant of byte stuffing methods to build frames to send and receive data. To delimit the frame, control characters - 0x02 and 0x03- are defined as start of text (STX) and end of text (ETX) respectively. For error detection, exclusive-or of data bytes is appended after the ETX as a checksum. If you need better error detection, CRC as described at
CRC Calculation in VB and C
can also be used.
For example, if we want to send two bytes of data -
Byte Stuffing on GitHub
The following is the C++ code to build, send and receive a frame.
CRC Calculation in VB and C
can also be used.
For example, if we want to send two bytes of data -
0x30 0x31,the resulting frame will be
0x02 0x30 0x31 0x03 0x01,where 0x02 at the start is added as STX, followed by data bytes and the byte before the last one, 0x03, is added as ETX. Since the exclusive-or of data bytes, 0x02^0x03, is 0x01, it is appended at the end as checksum. How can we send data that contains 0x02 or 0x03 which were already used as control characters? We need to define another control character 0x10 as Data Link Escape (DLE) to mark data that are not control characters. As an another example, let us build a frame for five data bytes -
0x30 0x02 0x65 0x10 0x03.We will do byte stuffing by putting DLE in front of every data byte that conflicts with STX, ETX, or DLE. And
0x02 0x30 0x10 0x02 0x65 0x10 0x10 0x10 0x03 0x03 0x44will be the resulting frame. I have developed a few programs in C and LabVIEW. Example programs can be downloaded at the following links.
Byte Stuffing on GitHub
The following is the C++ code to build, send and receive a frame.
// Byte stuffing- sending and receiving frames // Author: Yan Naing Aye #ifndef FRAME_H #define FRAME_H #include#define STX 0x02 #define ETX 0x03 #define DLE 0x10 #define TX_BUF_SIZE 128 #define RX_BUF_SIZE 128 enum RX_STATE { IGNORE,RECEIVING,ESCAPE,RXCRC1,RXCRC2 }; //----------------------------------------------------------------------------- class Frame { RX_STATE rState; protected: int TxN;//number of transmitting bytes int RxN;//number of receiving bytes char tb[TX_BUF_SIZE];//transmit buffer char rb[RX_BUF_SIZE];//receiving data public: Frame(); int setTxFrame(char* d,int n); unsigned int CRC16CCITT_Calculate(char* s,unsigned char len,unsigned int crc); int getTxN(); int getRxN(); int receiveRxFrame(char c);//get receiving frame from received char char* getTxBuf(); char* getRxBuf(); }; //----------------------------------------------------------------------------- Frame::Frame():TxN(0),RxN(0),rState(IGNORE){} //----------------------------------------------------------------------------- char* Frame::getTxBuf(){ return tb; } //----------------------------------------------------------------------------- char* Frame::getRxBuf(){ return rb; } //----------------------------------------------------------------------------- //Prepare transmitting frame int Frame::setTxFrame(char* d,int n) { unsigned int txcrc=0xFFFF;//initialize crc char c; int i=0,j=0; tb[i++]=STX;//start of frame for(j=0;j < n;j++) { c=d[j]; if((c==STX)||(c==ETX)||(c==DLE)) tb[i++]=(DLE); tb[i++]=c; } tb[i++]=(ETX);//end of frame txcrc=CRC16CCITT_Calculate(d,n,txcrc);//calculate crc tb[i++]=txcrc & 0xFF; tb[i++]=(txcrc >> 8) & 0xFF; TxN=i; return TxN; } //----------------------------------------------------------------------------- //Inputs //s : pointer to input char string //len: string len (maximum 255) //crc: initial CRC value //Output //Returns calculated CRC unsigned int Frame::CRC16CCITT_Calculate(char* s,unsigned char len,unsigned int crc) { //CRC Order: 16 //CCITT(recommendation) : F(x)= x16 + x12 + x5 + 1 //CRC Poly: 0x1021 //Operational initial value: 0xFFFF //Final xor value: 0 unsigned char i,j; for(i=0;i < len;i++,s++) { crc^=((unsigned int)(*s) & 0xFF) << 8; for(j=0;j<8;j++) { if(crc & 0x8000) crc=(crc << 1)^0x1021; else crc <<=1; } } return (crc & 0xFFFF);//truncate last 16 bit } //----------------------------------------------------------------------------- //get number of transmitting bytes int Frame::getTxN() { return TxN; } //----------------------------------------------------------------------------- //get number of transmitting bytes int Frame::getRxN() { return RxN; } //----------------------------------------------------------------------------- //process receiving char int Frame::receiveRxFrame(char c) { static char b; unsigned int crc; unsigned int rxcrc=0xFFFF;//initialize CRC switch(rState){ case IGNORE: if(c==STX) { rState=RECEIVING;RxN=0;} break; case RECEIVING: if(c==STX) { rState=RECEIVING;RxN=0;} else if(c==ETX){rState=RXCRC1;} else if(c==DLE){ rState=ESCAPE; } else { rb[RxN++]=c; } break; case ESCAPE: rb[RxN++]=c; rState=RECEIVING; break; case RXCRC1: b=c; rState=RXCRC2; break; case RXCRC2: rState=IGNORE; crc=( (int)c << 8 | ((int)b & 0xFF) ) & 0xFFFF;//get received crc rxcrc=CRC16CCITT_Calculate(rb,RxN,rxcrc);//calculate crc //printf("crc: %x rxcrc:%x \n",crc,rxcrc); if(rxcrc==crc){return RxN;}//if crc is correct else {RxN=0;}//discard the frame break; } return 0; } //----------------------------------------------------------------------------- //############################################################################# class Frame2:public Frame { char Dt[20];//transmitting data public: Frame2(); void printTxFrame(); void printRxFrame(); void printRxData(); void setTxData(float x,float y,float z,float b,float t); }; //----------------------------------------------------------------------------- Frame2::Frame2():Frame(),Dt(""){} //----------------------------------------------------------------------------- //Print out frame content void Frame2::printTxFrame() { printf("Tx frame buffer: "); for(int j=0;j < TxN;j++) printf("%02X ",(unsigned char)tb[j]); printf("\n"); } //----------------------------------------------------------------------------- //Print out frame content void Frame2::printRxFrame() { printf("Rx data buffer: "); for(int j=0;j < RxN;j++) printf("%02X ",(unsigned char)rb[j]); printf("\n"); } //----------------------------------------------------------------------------- //Set transmitting data void Frame2::setTxData(float x,float y,float z,float b,float t) { *(float*)(Dt)=x; *(float*)(Dt+4)=y; *(float*)(Dt+8)=z; *(float*)(Dt+12)=b; *(float*)(Dt+16)=t; Frame::setTxFrame(Dt,20); } //----------------------------------------------------------------------------- //Print out received data void Frame2::printRxData() { float x,y,z,b,t; x=*(float*)(Dt); y=*(float*)(Dt+4); z=*(float*)(Dt+8); b=*(float*)(Dt+12); t=*(float*)(Dt+16); printf("Rx data: %f %f %f %f %f \n",x,y,z,b,t); } //----------------------------------------------------------------------------- #endif // FRAME_H
Friday, June 18, 2010
Common Interrupt Pitfalls
I just want to share some interesting facts that I found in SDCC Compiler User Guide.
From my experience, I think these facts are very important to keep in mind of a firmware programmer. Last time, I got an experience that my program executed wrongly even though I could not find any fault in my program. Suddenly, I remembered stack overflow problem and the program worked correctly after I changed the stack size.
Variable not declared volatile
If an interrupt service routine changes variables which are accessed by other functions these variables have to be declared volatile. See http://en.wikipedia.org/wiki/Volatile_variable.Non-atomic access
If the access to these variables is not atomic (i.e. the processor needs more than one instruction for the access and could be interrupted while accessing the variable) the interrupt must be disabled during the access to avoid inconsistent data. Access to 16 or 32 bit variables is obviously not atomic on 8 bit CPUs and should be protected by disabling interrupts. You’re not automatically on the safe side if you use 8 bit variables though. For example, on the 8051 the harmless looking ”flags |= 0x80;” is not atomic if flags resides in xdata. Setting ”flags |= 0x40;” from within an interrupt routine might get lost if the interrupt occurs at the wrong time. ”counter += 8;” is not atomic on the 8051 even if counter is located in data memory. Bugs like these are hard to reproduce and can cause a lot of trouble.Stack overflow
The return address and the registers used in the interrupt service routine are saved on the stack so there must be sufficient stack space. If there isn’t enough stack space, variables or registers (or even the return address itself) will be corrupted. This stack overflow is most likely to happen if the interrupt occurs during the ”deepest” subroutine when the stack is already in use for i.e. many return addresses.Use of non-reentrant functions
Calling other functions from an interrupt service routine is not recommended, avoid it if possible. Furthermore nonreentrant functions should not be called from the main program while the interrupt service routine might be active. They also must not be called from low priority interrupt service routines while a high priority interrupt service routine might be active. You could use semaphores or make the function critical if all parameters are passed in registers. Good luck with your programming!Thursday, June 10, 2010
Circular Buffered UART Com Module for 8051 Microcontroller
A lot of embedded systems uses UART communication. That is why, I would like to share a circular buffered UART comm module here. I have developed the module for 8051 microcontroller but it can easily be modified for other microcontrollers as well.
UART-Timer-8051 on GitHub
Using Circular Buffered UART Com Module
You need to put the header files in the module you want to use them. In my example, I put all my header files into 'headers.h' file and I just need to include that file. Transmit and receive buffer sizes need to be defined in ComConfig.h file. And then, define a function to call on receive event. In the main function, poll the ComChkRx() function to retrieve the received data from the buffer. The source code for the example can be seen atUART-Timer-8051 on GitHub
Thursday, June 3, 2010
Soft-Timer Module for 8051 Microcontroller
Almost every embedded system uses timers in their firmware. 8051 microcontroller has only two or three hardware timers, and generally, it is not enough to use hardware for all the timers your system needs to have.
Furthermore, not all timers need to have hard timing requirement. For example, blinking an LED indicator every second is accurate enough if the timing error is less than a few millisecond.
That is why, I normally use software to implement all the timers that have soft timing requirement. Here, I would like to share a soft-timer module that I developed for 8051 microcontroller but it can easily be modified for other microcontrollers as well.
The source code for the example can be seen at
UART-Timer-8051 on GitHub
Write a function to be called when the timer time out. Write another function to set the timing parameters and start the timer. In my example, they are SysSBYLEDTmrTO() and SysSBYLEDInit() in System.c module.
Open TmrConfig.h and follow the 3 steps as indicated in the comment. If your compiler does not support function pointers, you can always replace with switch structure.
In the main function, initialize and poll the timer module by calling TmrInit() and TmrTask() respectively which are defined in Tmr.c module.
UART-Timer-8051 on GitHub
Using soft-timer module
You need to put the header files for soft-timer in the module you want to use them. In my example, I put all my header files into 'headers.h' file and I just need to include that file.Write a function to be called when the timer time out. Write another function to set the timing parameters and start the timer. In my example, they are SysSBYLEDTmrTO() and SysSBYLEDInit() in System.c module.
Open TmrConfig.h and follow the 3 steps as indicated in the comment. If your compiler does not support function pointers, you can always replace with switch structure.
In the main function, initialize and poll the timer module by calling TmrInit() and TmrTask() respectively which are defined in Tmr.c module.
Wednesday, May 26, 2010
Using SPI on Low-End Microcontroller
SPI is a simple and efficient inter-IC communication bus. A lot of peripheral chips such as Real Time Clock and EEPROM come with SPI or I2C bus. If there is no special reason, I prefer to use SPI than I2C because it is faster and simpler. It is also very easy to emulate in software.
Last time, I used 10MHz SPI LED driver chip with low end 4MHz microcontroller. Design priority was cost efficiency. Microcontroller cost less than a dollar but it had enough flash to store the firmware and a few display fonts. At first, I used interrupt and circular buffers to send and receive to and from SPI bus. I just wrote to the buffer and let the hardware and interrupt handled all the communication tasks as I usually do with slower long distance buses such as RS232 and CAN bus. It was OK in normal condition. The problem was that I wanted to update big 96x16 dot-matrix LED at the frame rate of 125Hz and the CPU utilization was very high. Consequently, it could not perform fast enough when it was executing some simple graphic manipulation tasks such as scrolling the text. Later, I realized that the most used SPI function where CPU spent most of its time was not efficient. Using hardware interrupt is more efficient normally, but it was different in this case- slow CPU with very fast and heavily used SPI. For each byte to SPI, send and receive interrupt functions which cost a lot of CPU cycles had to be performed. I found polling or emulation is faster than using interrupt to send a byte to SPI. Polling is still limited to the bus speeds supported by the hardware. After I modified the firmware to improve SPI function and it worked well. According to my experience, let me highlight some advantages of emulating SPI .
Last time, I used 10MHz SPI LED driver chip with low end 4MHz microcontroller. Design priority was cost efficiency. Microcontroller cost less than a dollar but it had enough flash to store the firmware and a few display fonts. At first, I used interrupt and circular buffers to send and receive to and from SPI bus. I just wrote to the buffer and let the hardware and interrupt handled all the communication tasks as I usually do with slower long distance buses such as RS232 and CAN bus. It was OK in normal condition. The problem was that I wanted to update big 96x16 dot-matrix LED at the frame rate of 125Hz and the CPU utilization was very high. Consequently, it could not perform fast enough when it was executing some simple graphic manipulation tasks such as scrolling the text. Later, I realized that the most used SPI function where CPU spent most of its time was not efficient. Using hardware interrupt is more efficient normally, but it was different in this case- slow CPU with very fast and heavily used SPI. For each byte to SPI, send and receive interrupt functions which cost a lot of CPU cycles had to be performed. I found polling or emulation is faster than using interrupt to send a byte to SPI. Polling is still limited to the bus speeds supported by the hardware. After I modified the firmware to improve SPI function and it worked well. According to my experience, let me highlight some advantages of emulating SPI .
- It can sometimes be better in performance to emulate SPI in software.
- It is more reliable because it is simpler and it can avoid potential pitfalls of using interrupt.
- It is faster, easier and less error prone to write a simple code rather than reading datasheet for variety of register settings for every new microcontroller you encountered.
- Most importantly, it is portable and it is not dependent on hardware.
//-------------------------------------
unsigned char spi(unsigned char d)
{
unsigned char i;
SCLK=1;
EN=1;
for(i=0;i<8;i++)
{
MOSI=(d & 0x80)?1:0;
//Delay(period/2)-optional for slower SPI bus speed
SCLK=0;
d<<=1;
d|=MISO;
//Delay(period/2)-optional for slower SPI bus speed
SCLK=1;
}
EN=0;
return d;
}
//-------------------------------------
Wednesday, April 28, 2010
C Programming on Windows
Some of my friends who started learning C programming have asked me which IDE is good to use on Windows.
For me, I personally like to use Microsoft Visual Studio Express which is available for free at http:// www.microsoft.com /express/
Dev-C++ from Bloodshed is also a popular one and it can be downloaded from http:// www.bloodshed.net/ devcpp.html.
The following is an example to create new C project on Visual C++ 2008 Express Edition. Go to File menu>>New>>Project... New Project window will appear. Select Win32 in Project types: Visual C++ Select Win32 Console Application in Templates: Visual Studio Installed templates Enter project name in the name text box and browse the folder to save the project. Click OK. Win32 Application Wizard box will appear. Click Next. Choose Console application for Application type and Check Empty project in additional options: Click Finish button. In the Solution Explorer window near the left, right click Source Files and click Add>>New Item... as shown in the following picture.
Add new item window will appear.
In the Name text box, enter the file name with .c extension e.g. StrPos.c
I have been frequently asked how to write a program to find the case insensitive string without using C library functions and the following is an example.
Dev-C++ from Bloodshed is also a popular one and it can be downloaded from http:// www.bloodshed.net/ devcpp.html.
The following is an example to create new C project on Visual C++ 2008 Express Edition. Go to File menu>>New>>Project... New Project window will appear. Select Win32 in Project types: Visual C++ Select Win32 Console Application in Templates: Visual Studio Installed templates Enter project name in the name text box and browse the folder to save the project. Click OK. Win32 Application Wizard box will appear. Click Next. Choose Console application for Application type and Check Empty project in additional options: Click Finish button. In the Solution Explorer window near the left, right click Source Files and click Add>>New Item... as shown in the following picture.
Add new item window will appear.
In the Name text box, enter the file name with .c extension e.g. StrPos.c
I have been frequently asked how to write a program to find the case insensitive string without using C library functions and the following is an example.
#include <stdio.h>
typedef signed char CHAR;
typedef signed int POSITION;
#define ToL(c) (((c)>='A')&&((c)<='Z')?(c+0x20):(c))
POSITION strcmp(CHAR* s1,CHAR* s2)
{
for(;*s2;s1++,s2++) if(ToL(*s1)!=ToL(*s2)) return 0;
return 1;
}
POSITION stripos (CHAR* haystack,CHAR* needle,POSITION offset)
{
for(;*(haystack+offset);offset++) if(strcmp(haystack+offset,needle)) return offset;
return -1;
}
int main(int argc,char *argv[])
{
CHAR str1[]="Hello! Good morning!";
CHAR str2[]="good";
printf("\nFound at: %d \n",stripos(str1,str2,0));
return 0;
}
After that, you can run the program by pressing F5 or by clicking Debug menu>>Start Debugging.
You can also click Debug menu>>Start Without Debugging.
Friday, September 25, 2009
CRC Calculation in VB and C
Just to share a few software modules that were written in Visual Basic 2005 and C for the calculation of CRC -Cyclic Redundancy Check.
CRC Calculation - GitHub
An example usage for calculation of CRC16 CCITT is shown below.
Initial value for CRC16 CCITT is 0xFFFF. The following example calculate CRC for Str1 and use that CRC value as initial value to calculate Str2.
CRC Calculation - GitHub
An example usage for calculation of CRC16 CCITT is shown below.
Online checksum calculator such as the following one may be useful to debug the code.
Online Checksum Calculator
CRC Calculation in VB2005
The followings are the source code for various CRC calculations in VB2005. To make the calculation faster, they use CRC tables.CRC Calculation - GitHub
An example usage for calculation of CRC16 CCITT is shown below.
Dim StrIn as String= "String to calculate CRC" Dim CRCVal16 As UInt16 = 0 Dim crc As String CRCVal16 = CRC16_CCITT.Calculate(StrIn) crc = CRC16_CCITT.ToString(CRCVal16)
Initial value for CRC16 CCITT is 0xFFFF. The following example calculate CRC for Str1 and use that CRC value as initial value to calculate Str2.
CRCVal16 = CRC16_CCITT.Calculate(Str1) CRCVal16 = CRC16_CCITT.Calculate(Str2, CRCVal16) crc = CRC16_CCITT.ToString(CRCVal16)
CRC Calculation in C
The followings are the source code for various CRC calculations in C. To save storage, they do not use CRC tables .CRC Calculation - GitHub
An example usage for calculation of CRC16 CCITT is shown below.
#define STRLEN 4
char str[STRLEN]={0x01,0x01,0x00,0x0B};
unsigned char c[2];
unsigned int crc;
//Calculate CRC16 CCITT
crc=CRC16CCITT_InitialValue();
crc=CRC16CCITT_Calculate(str,STRLEN,crc);
CRC16CCITT_ToString(crc,c);
printf("CRC16 CCITT = %02X %02X \n",c[0],c[1]);
Online checksum calculator such as the following one may be useful to debug the code.
Online Checksum Calculator
Tuesday, August 18, 2009
SDCC - Small Device C Compiler
SDCC - Small Device C Compiler - is a free open source C compiler software for 8051 and a few other microcontrollers.
Unlike SDCC, there are other popular commercially available compilers such as Keil that you can purchase. You can download a free evaluation version there but that trial version is limited to 2k byte code size. A good thing about SDCC is that you can get it for free at no cost.
This post is just an overview of SDCC manual at http://sdcc.sourceforge.net/doc/sdccman.pdf. Writing and compiling of a few example C programs on Windows for 8051 are also discussed.
Installing
Go to http://sdcc.sourceforge.net/ and download the setup program Run the setup program and follow the installation process.
Testing the SDCC Compiler
To test the installation of the compiler whether it is OK or not, go to command prompt and enter "sdcc -v". This should return sdcc's version number.
Example C Program
Type in the following example program using your favorite ASCII editor and save as led.c. This is an example C program for 8051 microcontroller to blink an LED connected to P3.4 pin.
Compiling and Getting Hex File
Go to the path where led.c is located and enter "sdcc led.c". If all goes well the compiler will link with the libraries and produce a led.ihx output file. You can enter "dir" to see if there is led.ihx file. After that, enter "packihx led.ihx>led.hex" to get the intel hex file that is suitable to download into your chip.
Projects with Multiple Source Files
SDCC can compile only ONE file at a time. Let us, for example, assume that you have a project containing the following file: main.c blink.c Type in the following example code in these files.
The files without main() function will need to be compiled separately with the commands: "sdcc -c blink.c". Then compile the source file containing the main() function and link the files together with the command- "sdcc main.c blink.rel". You will get main.ihx file and then you can get main.hex file as discussed before.
Installing
Go to http://sdcc.sourceforge.net/ and download the setup program Run the setup program and follow the installation process.
Testing the SDCC Compiler
To test the installation of the compiler whether it is OK or not, go to command prompt and enter "sdcc -v". This should return sdcc's version number.
Example C Program
Type in the following example program using your favorite ASCII editor and save as led.c. This is an example C program for 8051 microcontroller to blink an LED connected to P3.4 pin.
#include<8052.h>
void main()
{
int i;
while(1)
{
P3_4=0; //Output 0
for(i=0;i<30000;i++); //delay loop
P3_4=1; //Output 1
for(i=0;i<30000;i++); //delay loop
}
}
Compiling and Getting Hex File
Go to the path where led.c is located and enter "sdcc led.c". If all goes well the compiler will link with the libraries and produce a led.ihx output file. You can enter "dir" to see if there is led.ihx file. After that, enter "packihx led.ihx>led.hex" to get the intel hex file that is suitable to download into your chip.
Projects with Multiple Source Files
SDCC can compile only ONE file at a time. Let us, for example, assume that you have a project containing the following file: main.c blink.c Type in the following example code in these files.
//File name: main.c
#include "blink.h"
void main()
{
while(1)
{
toggle();
delay();
}
}
//File name: blink.c
#include <8052.h>
#include "blink.h"
void toggle()
{
P3_4^=1;
}
void delay()
{
int i;
for(i=0;i<30000;i++); //delay loop
}
//File name: blink.h void toggle(); void delay();
The files without main() function will need to be compiled separately with the commands: "sdcc -c blink.c". Then compile the source file containing the main() function and link the files together with the command- "sdcc main.c blink.rel". You will get main.ihx file and then you can get main.hex file as discussed before.
Subscribe to:
Posts (Atom)






