Simple electronic recorder
First was an idea
At work (I work in medicine) two electromechanical recorders puff and suffer, well, I and them: mascara, mechanics - you know it’s unpleasant. Once, an idea came into my head: why not replace the two recorders choking on old age with a simple data collection system consisting of an ADC controller and a PC (even a weak and old one) with the appropriate software with the ability to output to a printer? And then it started in my head and spun ...
Lyrics
Since I had nothing except an idea: neither experience nor special knowledge in circuitry and electronics, I had to shovel a fair amount of literature and rummage around the vastness of the network. Also, the project was supposed to be budgetary, and therefore I had to master the LUT method, learn how to etch boards, drill and solder - which I have no regrets about. Thus, I went through some, albeit small, path - the path of trial and error, I bring some observations made by me in the process, maybe someone will compare them with their own and agree, or maybe not agree:
- a quick start, like this, will not work, do not build illusions - you have to sweat;
- at first, it’s better not to use emulators like Proteus, it’s much more useful to experiment on real hardware, touch your hands, taste and taste. UART is enough for simple debugging;
- circuit boards - brr, I prefer LUT + ferric chloride + drilling, it turns out a little longer, but gives a clear understanding of what you are doing;
- I advise you not to get involved in installing smd cases and “miniaturizing” circuit boards - this is quite difficult for a beginner, sometimes it can be easier to re-mount the board on an “increased scale” with a simple hinged installation (again, more useful for understanding).
About ADC theory and the first attempt
After some research, it turned out that it is possible to realize the idea in several ways. The simplest solutions are given in the book of Patrick Gell (see the basement), the basics of analog-to-digital signal conversion are also explained there. Here is a typical diagram taken from there:
The circuit is based on an ADC chip. Interaction with a PC is implemented at the software level by forming control sequences of pulses on the modem lines of the RS-232 interface of a PC. This circumstance limits the data rate and increases the likelihood of transmission errors. The measurement accuracy is determined by the resolution of the ADC (in this case, 8 bits), the accuracy of the reference voltage supplied to the ADC (ION LT 1009 CZ is used here). The signal digitization speed depends on the ADC conversion time and, again, on the accuracy of the interface organization by the developer. Actually, this implementation was my first combat experience (see photo below), but soon disappointed me, because I felt the need for a more elegant solution. The control program (driver) was written under DOS in Pascal.
Such schemes, in spite of their viability, are practically not applied due to the indicated shortcomings, ADC microcircuits are usually used together with a microcontroller, which already organizes data transfer at the hardware level, simultaneously performing some control operations or primitive data processing. A good example of such a solution is such a circuit based on the AVR microcontroller:
The circuit is based on the Atmega8 microcontroller, FT232BM USB interface chip, AD7876 ADC chip, and REF195GP ION. At the input, a differentiator based on an operational amplifier brings the input signal to a range of 0-5V (ADC reference voltage). The AD7876 ADC chip performs analog-to-digital signal conversion and transmits the data via the SPI interface to the microcontroller, which, in turn, “throws” the result to the usb port using the UART and FT232BM interface microcircuit.
As part of my task, I need to use the 4 ADC channels. An attractive opportunity is to use the built-in ADC of the microcontroller with a switched input, which will allow you to refuse to use an external ADC chip and provide the required number of channels - a cheap and simple solution. It is not necessary to include a differentiator in the circuit, since the amplitude of the signal at each of the inputs does not exceed 2-2.5 V.
The scheme of my device
The ADC controller is built on the AVR Atmega8 microcontroller. MK has enough legs to connect 4 ADC channels, signal LEDs, PC interface card. The circuit uses an external ION L1009CZ. The PC interface card via the RS-232 interface is based on the MAX232 chip and is isolated from the main module; if necessary, it can be replaced by a card with the FT232 on board for USB interface, or with any bluetooth module (type BTM-222 , HC-04 ) for communication via blootooth interface. The figure below shows a schematic diagram of the device under development:
The power circuit is standard - based on the linear stabilizer 78L05, there is a signal LED HL1. The schematic diagram is drawn using sPlan, the layout of the board is in Sprint Layout. At the end of the technological chain - LUT + etching + drilling + soldering, we get:
Bottom view:
Software part
For coding, I used AVRStudio + WinAVR (AVR-GCC) for Windows, the alternative for Linux is Eclipse + AVR-GCC. I tried CodeVisionAVR - not bad for a start, it has a built-in code generator, the limit on the amount of code is 2 kB.
The firmware works according to the following algorithm:
- initialization: functions - UART_init, ADC_init, LED_init;
- serial interrogation of channels in an endless loop for interruption and data transfer via UART to the PC com-port.
In order to debug the text, test messages are considered. Switching the polling channel is highlighted by the corresponding LED. During initialization, all 4 LEDs blink simultaneously. In order for the switching of the LEDs to be noticeable to the eye, I deliberately set delays.
/* WinAVR version...
Chip: ATmega8
Memory Model: SMALL
Data Stack Size: 256 bytes
Clock frequency: 4.0000 MHz
PCO - PC3 - Channels */// ATmega8 I/O register definitions#include<avr/io.h>#include<util/delay.h>#include<avr/interrupt.h>#include<stdio.h>#define ADC_VREF_TYPE 0x40#define ADC_CH1_MUX 0x1#define ADC_CH2_MUX 0x2#define ADC_CH3_MUX 0x3// Counter of channel's changesuint8_t i = 0;
voidLED_init(void){
printf("Led initialization....\r\n");
char j = 0;
DDRD|= (1<<DDD7);
DDRB|= ((1<<DDB0)|(1<<DDB1)|(1<<DDB2));
for(j=0;j<5;j++)
{
PORTD|=(1<<PD7);
PORTB|=(1<<PB0)|(1<<PB1)|(1<<PB2);
_delay_ms(600);
PORTB&= ~((1<<PB0)|(1<<PB1)|(1<<PB2));
PORTD&= ~(1<<PD7);
_delay_ms(600);
}
}
//Sending of single charstaticintmy_putchar(char c, FILE *stream){
while((UCSRA&(1<<UDRE)) == 0);
UDR = c;
return0;
}
voidmyUART_init(void){
// USART initialization// Communication Parameters: 8 Data, 1 Stop, No Parity// USART Receiver: Off// USART Transmitter: On// USART Mode: Asynchronous// USART Baud rate: 9600
UCSRA=0x00;
UCSRB=0x08;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x19;
//Redirection of stdoutstatic FILE mystdout = FDEV_SETUP_STREAM(my_putchar, NULL, _FDEV_SETUP_WRITE);
stdout = &mystdout;
printf("UART initialization....\r\n");
}
voidADC_init(void){
// ADC initialization// ADC Voltage Reference: AREF pin// ADC High Speed Mode: Off// ADC Auto Trigger Source: None// Select ADC input 0printf("ADC initialization....\r\n");
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x8E;
}
// ADC interrupt service routine
ISR(ADC_vect){
// Here is sending data in RS-232printf("I'am in interrupt...\r\n");
uint16_t data = ADCL;
data+= (ADCH<<8);
printf("Ch_%u=%u\r\n",i,data);
//Control of ADMUX's stateuint8_t pr = ADMUX;
printf("ADMUX = %u\r\n",pr);
data = 0;
if (i == 3)
{
i = 0;
ADMUX&= ~ADC_CH3_MUX;
PORTB&= ~(1<<PB2);
PORTD|=(1<<PD7);
//Change of channel
data = ADMUX;
printf("3to0,ADMUX = %u\r\n",data);
data=0;
_delay_ms(25);
}
else
{
if (i == 0)
{
ADMUX|= ADC_CH1_MUX;
PORTD&= ~(1<<PD7);
PORTB|= (1<<PB0);
//Change of channel
data = ADMUX;
printf("0to1,ADMUX = %u\r\n",data);
data=0;
}
if (i == 1)
{
ADMUX&= ~ADC_CH1_MUX;
ADMUX|= ADC_CH2_MUX;
PORTB&= ~(1<<PB0);
PORTB|= (1<<PB1);
//Change of channel
data = ADMUX;
printf("1to2,ADMUX = %u\r\n",data);
data=0;
}
if (i == 2)
{
ADMUX&= ~ADC_CH2_MUX;
ADMUX|= ADC_CH3_MUX;
PORTB&= ~(1<<PB1);
PORTB|= (1<<PB2);
//Change of channel
data = ADMUX;
printf("2to3,ADMUX = %u\r\n",data);
data=0;
}
i++;
_delay_ms(25);
}
// Start a new AD conversion
ADCSRA|=0x40;
};
intmain(void){
myUART_init();
ADC_init();
LED_init();
printf("I'am in main...\r\n");
// Global enable interrupts
sei();
// Start the first AD conversion
ADCSRA|=0x40;
while (1);
}
After debugging is complete, test messages need to be commented out and unnecessary delays removed. The code was written buried in the datasheet , everything is written in detail there.
Programmer
For firmware, the simplest STK200 programmer was used , and the board wiring had to be done on its own in order to facilitate soldering. Stitched avrdude. I tried avreal - a great alternative, there were no difficulties either.
Finally, it works!
After debugging the code, several erase / write cycles, the MK device came to life and blinked LEDs to my great joy.
On a PC I used a text terminal to work with a COM port. In the network of their bulk, and if you wish you can write to, for example, using + the QT QSerialDevice (wonderful library of to work with the com-ports, written by our compatriot Denis Shienkovym), or here .
Finally
The plans are only writing software for the PC. Actually, I’m already writing using QT + QSerialDevice + QWT in a bunch , and soon, soon, I feel that my graphs will crawl on the display. And I’m also thinking about implementing hardware on the STM32F series MK, taking as a basis the STM32VLDISCOVERY already mentioned on the hub - I want to learn new hardware.
Useful literature
Help digest all the above books:
P. Horowitz, W. Hill. “The art of circuitry” is a classic thing;
Patrick Gell. How to turn a personal computer into a measuring complex was mentioned above.