This circuit is used to increase the sensitivity for the microphone, so it can "hear" from longer distance. The microphone has 2 terminals: mic+ and mic-.
Here is the amplifier with only 1 transistor:
For more sensitivity, use this circuit with 2 transistors:
microelefun
electronic projects and circuits
Wednesday, September 18, 2013
Sunday, January 6, 2013
simplest voltage regulator
For projects where you use a microcontroller for example which works at 5V, if you want to interface a 3.3V module (accelerometer, sd card, bluetooth adapter, etc.), you need to somehow convert 5V to 3.3V. There are many cheap voltage regulators on the market, but if you rapidly need one, you can use this simple circuit instead, which will do the job pretty well.
With the given values, the output voltage is about 3.04V for 100 Ohm load, 2.95V for 33 Ohm load, and 3.14V for 2 KOhm load. You can ajust the output voltage by modifying the R1 and R2 vlaues.
With the given values, the output voltage is about 3.04V for 100 Ohm load, 2.95V for 33 Ohm load, and 3.14V for 2 KOhm load. You can ajust the output voltage by modifying the R1 and R2 vlaues.
Saturday, November 10, 2012
Simple LiPo / Li-Ion Charger
Disclaimer: Charging LiPo / Li-Ion batteries is dangerous! Better use a comercial professional charger. If you choose to build the charger described here, use it at your own risk.
To charge a LiPo / Li-Ion cell, it is supplied with constant current until it reaches 4.2V (depends on cell, usually 4.2V). This is what the circuit does: the current is limited to 0.7/Rc, where 0.7 is the Vbe of BC337, and the voltage limit is adjustable from the potentiometer (with a voltmeter connected instead of battery). LED1 indicates if the battery polarity is OK. LED2 indicates if the battery is charged. The transistor D882 dissipates the unused power, so it needs a radiator. It is a good idea to place the transistors close to each other, because at high temperature the Vbe of BC337 will decrease, so the current will decrease. The diode is used for protecting the circuit from reverse polarity of the cell. Almost any high-current diode can be used.
Friday, November 2, 2012
PIC18F4550 Snake Game on 128x64 GLCD v2
much better graphics :) enjoy!
source code: (PIC18F4550, CCS C)
file kbd.h:
#define keyUp PIN_B2
#define keyDown PIN_B3
#define keyLeft PIN_B4
#define keyRight PIN_B5
#define keyA PIN_B6
#define keyB PIN_B7
#define keyUpPressed !input(keyUp)
#define keyDownPressed !input(keyDown)
#define keyLeftPressed !input(keyLeft)
#define keyRightPressed !input(keyRight)
#define keyAPressed !input(keyA)
#define keyBPressed !input(keyB)
file glcd.c:
#ifndef GLCD_C
#define GLCD_C
#define ON 1
#define OFF 0
#define YES 1
#define NO 0
// GLCD PIN CONFIGURATION:
#bit GLCD_CS1 = porte.1
#bit GLCD_CS2 = porte.2
#bit GLCD_DI = portc.0
#bit GLCD_RW = porte.0
#bit GLCD_E = portc.1
#byte GLCD_DATA = portd
#bit tris_GLCD_CS1 = trise.1
#bit tris_GLCD_CS2 = trise.2
#bit tris_GLCD_DI = trisc.0
#bit tris_GLCD_RW = trise.0
#bit tris_GLCD_E = trisc.1
#byte tris_GLCD_DATA = trisd
////////////////////////////
// IO functions:
void glcdPulseE() {
GLCD_E = 1;
delay_us(10); // for more speed improve the data bus to glcd
GLCD_E = 0;
}
void glcdWrite1(unsigned int8 data) {
GLCD_CS1 = 1;
GLCD_RW = 0; // R/W = Write
GLCD_DATA = data;
tris_GLCD_DATA = 0;
GLCD_DATA = data;
glcdPulseE();
GLCD_CS1 = 0;
}
void glcdWrite2(unsigned int8 data) {
GLCD_CS2 = 1;
GLCD_RW = 0; // R/W = Write
GLCD_DATA = data;
tris_GLCD_DATA = 0;
GLCD_DATA = data;
glcdPulseE();
GLCD_CS2 = 0;
}
unsigned int8 glcdRead1() {
unsigned int8 data;
GLCD_CS1 = 1;
tris_GLCD_DATA = 0xFF; // input
GLCD_RW = 1; // R/W = Read
GLCD_E = 1;
delay_us(10);
GLCD_E = 0;
delay_us(10);
GLCD_E = 1;
delay_us(10);
data = GLCD_DATA;
GLCD_E = 0;
GLCD_CS1 = 0;
return data;
}
unsigned int8 glcdRead2() {
unsigned int8 data;
GLCD_CS2 = 1;
tris_GLCD_DATA = 0xFF; // input
GLCD_RW = 1; // R/W = Read
GLCD_E = 1;
delay_us(10);
GLCD_E = 0;
delay_us(10);
GLCD_E = 1;
delay_us(10);
data = GLCD_DATA;
GLCD_E = 0;
GLCD_CS2 = 0;
return data;
}
/////////////////////////////////////////
void glcdFillScreen(unsigned int8 color) {
int x, y;
if(color!=0) color = 0xFF;
for(x=0; x<8; x++) { // for all 8 rows of the glcd
GLCD_DI = 0; // D/I = Instruction
glcdWrite1(0b01000000); // start of the row
glcdWrite2(0b01000000);
glcdWrite1(x | 0b10111000); // Set row
glcdWrite2(x | 0b10111000);
GLCD_DI = 1; // D/I = Data
for(y=0; y<64; y++) { // fill columns of the row with pixels
glcdWrite1(color);
glcdWrite2(color);
}
}
}
void glcdInit(int1 active) { // 1 = on, 0 = off
GLCD_E = 0;
tris_GLCD_E = 0;
GLCD_E = 0;
GLCD_CS1 = 0;
tris_GLCD_CS1 = 0;
GLCD_CS1 = 0;
GLCD_CS2 = 0;
tris_GLCD_CS2 = 0;
GLCD_CS2 = 0;
GLCD_DI = 0;
tris_GLCD_DI = 0;
GLCD_DI = 0; // D/I = Instruction
GLCD_RW = 0;
tris_GLCD_RW = 0;
GLCD_RW = 0; // R/W = Write
glcdWrite1(0xC0);
glcdWrite2(0xC0);
glcdWrite1(0x40);
glcdWrite2(0x40);
glcdWrite1(0xB8);
glcdWrite2(0xB8);
glcdWrite1(0x3E + active); // turn on or off
glcdWrite2(0x3E + active);
glcdFillScreen(OFF);
}
void glcdClear() {
glcdFillScreen(OFF);
}
#endif
file main.c:
#include "18F4550.h"
#DEVICE PASS_STRINGS = IN_RAM
#fuses HSPLL, PLL5, CPUDIV1, NOWDT, NOPROTECT, PUT, BORV43, NOLVP, NOMCLR, USBDIV, VREGEN, WRT=14, WRTB
#use delay(clock=48000000)
#zero_ram
#byte porta = 0xF80
#byte portb = 0xF81
#byte portc = 0xF82
#byte portd = 0xF83
#byte porte = 0xF84
#byte trisa = 0xF92
#byte trisb = 0xF93
#byte trisc = 0xF94
#byte trisd = 0xF95
#byte trise = 0xF96
#byte ucon = 0xF6D
#bit usben = ucon.3
#byte ucfg = 0xF6F
#bit utrdis = ucfg.3
#include "kbd.h"
#include "glcd.c"
void cpu_init() {
usben = 0;
utrdis = 1;
setup_comparator(NC_NC_NC_NC);
SETUP_ADC_PORTS(NO_ANALOGS);
SETUP_ADC(ADC_OFF);
port_b_pullups(true);
}
unsigned int32 _Randseed;
unsigned int16 rand(void) {
_Randseed = _Randseed * 1103515245 + 12345;
return ((unsigned int16)(_Randseed >> 16) );
}
void srand(unsigned int32 seed) {
_Randseed = seed;
}
#define CODE_EMPTY '.'
#define CODE_FOOD 3
#define CODE_SNAKE 219
#define OFFSET_FOOD 0
#define OFFSET_SNVE 8
#define OFFSET_SNHO 16
#define OFFSET_SNDL 24
#define OFFSET_SNUL 32
#define OFFSET_SNUR 40
#define OFFSET_SNDR 48
#define OFFSET_SNHU 56
#define OFFSET_SNHR 64
#define OFFSET_SNHD 72
#define OFFSET_SNHL 80
#define OFFSET_SNTU 88
#define OFFSET_SNTR 96
#define OFFSET_SNTD 104
#define OFFSET_SNTL 112
const unsigned int8 BITMAP[] = {0b00011110, // food
0b00100001,
0b01000001,
0b10000010,
0b10000010,
0b01000001,
0b00100001,
0b00011110,
0b00000000, // snake_vertical
0b00000000,
0b11101110,
0b11101110,
0b01110111,
0b01110111,
0b00000000,
0b00000000,
0b00001100, // snake_horizontal
0b00111100,
0b00111100,
0b00110000,
0b00001100,
0b00111100,
0b00111100,
0b00110000,
0b00001100, // snake_down_left
0b00111100,
0b11111100,
0b11101000,
0b01111000,
0b01100000,
0b00000000,
0b00000000,
0b00001100, // snake_up_left
0b00111100,
0b00111110,
0b00010110,
0b00011111,
0b00000111,
0b00000000,
0b00000000,
0b00000000, // snake_up_right
0b00000000,
0b00000110,
0b00011110,
0b00010111,
0b00111111,
0b00111100,
0b00110000,
0b00000000, // snake_down_right
0b00000000,
0b11100000,
0b11111000,
0b01101000,
0b01111100,
0b00111100,
0b00110000,
0b00000000, // snake_head_up // link up, head looks down
0b01110000,
0b10011110,
0b11111110,
0b11111111,
0b10011111,
0b01110000,
0b00000000,
0b00111100, // snake_head_right // link right
0b01011010,
0b01011010,
0b01111110,
0b00111100,
0b00111100,
0b00111100,
0b00110000,
0b00000000, // snake_head_down // link down
0b00001110,
0b11111001,
0b11111111,
0b01111111,
0b01111001,
0b00001110,
0b00000000,
0b00001100, // snake_head_left // link left
0b00111100,
0b00111100,
0b00111100,
0b01111110,
0b01011010,
0b01011010,
0b00111100,
0b00000000, // snake_tail_up // link up
0b00000000,
0b00101110,
0b11101110,
0b11110111,
0b00110111,
0b00000000,
0b00000000,
0b00011000, // snake_tail_right // link right
0b00011000,
0b00111100,
0b00110000,
0b00001100,
0b00111100,
0b00111100,
0b00110000,
0b00000000, // snake_tail_down // link down
0b00000000,
0b11101100,
0b11101111,
0b01110111,
0b01110100,
0b00000000,
0b00000000,
0b00001100, // snake_tail_left // link left
0b00111100,
0b00111100,
0b00110000,
0b00001100,
0b00111100,
0b00011000,
0b00011000};
unsigned int8 arena[16][8]; // x, y
int snakeDir = 1;
unsigned int8 snakeX[100];
unsigned int8 snakeY[100];
unsigned int8 snakeLen = 3;
unsigned int8 snakeBitmapOffset(unsigned int8 x, unsigned int8 y) {
unsigned int8 i;
i = 0;
while(true) {
if(snakeX[i]==x && snakeY[i]==y) break;
i++;
}
if(i==0) {
if(snakeX[i+1]==x+1) return OFFSET_SNHR;
if(snakeX[i+1]==x-1) return OFFSET_SNHL;
if(snakeY[i+1]==y+1) return OFFSET_SNHD;
if(snakeY[i+1]==y-1) return OFFSET_SNHU;
}
if(i==snakeLen-1) {
if(snakeX[i-1]==x+1) return OFFSET_SNTR;
if(snakeX[i-1]==x-1) return OFFSET_SNTL;
if(snakeY[i-1]==y+1) return OFFSET_SNTD;
if(snakeY[i-1]==y-1) return OFFSET_SNTU;
}
if(snakeX[i+1]==x && snakeX[i-1]==x) return OFFSET_SNVE;
if(snakeY[i+1]==y && snakeY[i-1]==y) return OFFSET_SNHO;
if(snakeX[i+1]==x+1 && snakeY[i-1]==y+1) return OFFSET_SNDR;
if(snakeX[i-1]==x+1 && snakeY[i+1]==y+1) return OFFSET_SNDR;
if(snakeX[i+1]==x-1 && snakeY[i-1]==y+1) return OFFSET_SNDL;
if(snakeX[i-1]==x-1 && snakeY[i+1]==y+1) return OFFSET_SNDL;
if(snakeX[i+1]==x+1 && snakeY[i-1]==y-1) return OFFSET_SNUR;
if(snakeX[i-1]==x+1 && snakeY[i+1]==y-1) return OFFSET_SNUR;
if(snakeX[i+1]==x-1 && snakeY[i-1]==y-1) return OFFSET_SNUL;
if(snakeX[i-1]==x-1 && snakeY[i+1]==y-1) return OFFSET_SNUL;
return OFFSET_SNVE;
}
void glcdUpdate() {
unsigned int8 x, y, code, i;
unsigned int8 bitmapOffset;
for(y = 0; y < 8; y++) {
GLCD_DI = 0;
glcdWrite1(0b01000000);
glcdWrite2(0b01000000);
glcdWrite1(y | 0b10111000);
glcdWrite2(y | 0b10111000);
GLCD_DI = 1;
for(x=0; x<16; x++) {
code = arena[x][y];
if(code==CODE_SNAKE) {
bitmapOffset = snakeBitmapOffset(x, y);
if(x<8)
for(i=0; i<8; i++)
glcdWrite1(BITMAP[bitmapOffset+i]);
else
for(i=0; i<8; i++)
glcdWrite2(BITMAP[bitmapOffset+i]);
}/////////////////////////
if(code==CODE_EMPTY) {
if(x<8)
for(i=0; i<8; i++)
glcdWrite1(0x00);
else
for(i=0; i<8; i++)
glcdWrite2(0x00);
}/////////////////////////
if(code==CODE_FOOD) {
if(x<8)
for(i=0; i<8; i++)
glcdWrite1(BITMAP[OFFSET_FOOD+i]);
else
for(i=0; i<8; i++)
glcdWrite2(BITMAP[OFFSET_FOOD+i]);
}/////////////////////////
}
}
}
unsigned int8 score = 0;
void arena_clear() {
int x, y;
for(x=0; x<16; x++)
for(y=0; y<8; y++)
arena[x][y] = CODE_EMPTY;
}
void put_food() {
unsigned int8 x, y;
while(true) {
x = rand() % 16;
y = rand() % 8;
if(arena[x][y]!=CODE_SNAKE) {
arena[x][y] = CODE_FOOD;
break;
}
}
}
unsigned int8 move_snake() {
signed int8 tail_x, tail_y, head_x, head_y;
unsigned int8 i;
tail_x = snakeX[snakeLen-1];
tail_y = snakeY[snakeLen-1];
for(i=snakeLen-1; i>0; i--) {
snakeX[i] = snakeX[i-1];
snakeY[i] = snakeY[i-1];
}
head_x = snakeX[0];
head_y = snakeY[0];
switch(snakeDir) {
case 0: head_y--; break;
case 1: head_x++; break;
case 2: head_y++; break;
case 3: head_x--; break;
}
snakeX[0] = head_x;
snakeY[0] = head_y;
if(head_x < 0)
return -1;
if(head_y < 0)
return -1;
if(head_x >= 16)
return -1;
if(head_y >= 8)
return -1;
if(arena[head_x][head_y] != CODE_FOOD) { // nothing eaten
arena[tail_x][tail_y] = CODE_EMPTY; // cut tail
}
if(arena[head_x][head_y] == CODE_FOOD) {
snakeX[snakeLen] = tail_x;
snakeY[snakeLen] = tail_y;
snakeLen++;
arena[head_x][head_y] = CODE_SNAKE; // add head
return 2;
}
arena[head_x][head_y] = CODE_SNAKE; // add head
return 0;
}
int1 refreshSnakeDir() {
unsigned int8 oldDir;
oldDir = snakeDir;
if(keyUpPressed) snakeDir = 0;
if(keyRightPressed) snakeDir = 1;
if(keyDownPressed) snakeDir = 2;
if(keyLeftPressed) snakeDir = 3;
if(oldDir!=snakeDir)
return 1;
else
return 0;
}
void main() {
unsigned int8 i;
unsigned int8 res;
unsigned int1 dirChanged;
cpu_init();
delay_ms(100);
glcdInit(ON);
arena_clear();
snakeY[0] = 0;
snakeY[1] = 0;
snakeY[2] = 0;
snakeX[0] = 2;
snakeX[1] = 1;
snakeX[2] = 0;
arena[0][0] = CODE_SNAKE;
arena[1][0] = CODE_SNAKE;
arena[2][0] = CODE_SNAKE;
put_food();
glcdUpdate();
while(true) {
for(i=0; i<4; i++) {
dirChanged = refreshSnakeDir();
delay_ms(20);
dirChanged |= refreshSnakeDir();
delay_ms(20);
dirChanged |= refreshSnakeDir();
delay_ms(20);
dirChanged |= refreshSnakeDir();
delay_ms(20);
dirChanged |= refreshSnakeDir();
if( dirChanged || keyBPressed || keyAPressed )
break;
}
if(keyBPressed) {
delay_ms(20);
while(keyBPressed)
delay_ms(10);
while(!keyBPressed)
delay_ms(10);
while(keyBPressed)
delay_ms(10);
}
refreshSnakeDir();
res = move_snake();
if(res==2) {
score++;
put_food();
}
if(res==-1) {
glcdClear();
//glcdPutc("Game Over\r\nscore = ");
//glcdPutn(score);
delay_ms(1000);
reset_cpu();
}
glcdUpdate();
}
}
Monday, October 8, 2012
PIC18F4550 Snake Game on 128x64 GLCD
source code (for educational purpose only), simple copy-paste won't work :)
file snake.c:
#include <18F4550.h>
#DEVICE ADC=10
#fuses HSPLL, PLL3, CPUDIV1, NOWDT, NOPROTECT, PUT, NOBROWNOUT, NOLVP, MCLR
#define maxX 16
#define maxY 8
unsigned int8 matrix[maxY][maxX]; // y, x
int snake_dir = 1;
unsigned int8 snake_x[100];
unsigned int8 snake_y[100];
unsigned int8 snake_len = 3;
unsigned int8 score = 0;
void matrix_clear() {
int x, y;
for(x=0; x<maxX; x++)
for(y=0; y<maxY; y++)
matrix[y][x] = '.';
}
void drawSnakeCell(int x, int y) {
unsigned int8 sizeX, sizeY;
sizeX = 128 / maxX;
sizeY = 64 / maxY;
glcd_rect(x*sizeX, y*sizeY, (x+1)*sizeX-1, (y+1)*sizeY-1, YES, ON);
}
void drawFoodCell(int x, int y) {
unsigned int8 sizeX, sizeY;
sizeX = 128 / maxX;
sizeY = 64 / maxY;
glcd_rect(x*sizeX, y*sizeY, (x+1)*sizeX-1, (y+1)*sizeY-1, NO, ON);
}
void eraseCell(int x, int y) {
unsigned int8 sizeX, sizeY;
sizeX = 128 / maxX;
sizeY = 64 / maxY;
glcd_rect(x*sizeX, y*sizeY, (x+1)*sizeX-1, (y+1)*sizeY-1, YES, OFF);
}
void show() {
unsigned int8 x, y;
unsigned int8 i;
unsigned int8 sizeX, sizeY;
sizeX = 128 / maxX;
sizeY = 64 / maxY;
for(i=0; i<snake_len; i++)
matrix[snake_y[i]][snake_x[i]] = 219;
glcd_clear();
glcd_off();
for(y=0; y<maxY; y++) {
for(x=0; x<maxX; x++) {
if(matrix[y][x]==219)
glcd_rect(x*sizeX, y*sizeY, (x+1)*sizeX-1, (y+1)*sizeY-1, YES, ON);
if(matrix[y][x]==3)
glcd_rect(x*sizeX, y*sizeY, (x+1)*sizeX-1, (y+1)*sizeY-1, NO, ON);
}
}
glcd_on();
}
void put_food() {
unsigned int8 x, y;
while(true) {
x = rand() % maxX;
y = rand() % maxY;
if(matrix[y][x]!=219) {
matrix[y][x] = 3;
drawFoodCell(x, y);
break;
}
}
}
unsigned int8 move_snake() {
signed int8 tail_x, tail_y, head_x, head_y;
unsigned int8 i;
tail_x = snake_x[snake_len-1];
tail_y = snake_y[snake_len-1];
for(i=snake_len-1; i>0; i--) {
snake_x[i] = snake_x[i-1];
snake_y[i] = snake_y[i-1];
}
head_x = snake_x[0];
head_y = snake_y[0];
switch(snake_dir) {
case 0: head_y--; break;
case 1: head_x++; break;
case 2: head_y++; break;
case 3: head_x--; break;
}
snake_x[0] = head_x;
snake_y[0] = head_y;
if(head_x < 0)
return -1;
if(head_y < 0)
return -1;
if(head_x >= maxX)
return -1;
if(head_y >= maxY)
return -1;
if(matrix[head_y][head_x] != 3) { // nothing eaten
matrix[tail_y][tail_x] = '.'; // cut tail
eraseCell(tail_x, tail_y);
}
if(matrix[head_y][head_x] == 3) {
snake_x[snake_len] = tail_x;
snake_y[snake_len] = tail_y;
snake_len++;
matrix[head_y][head_x] = 219; // add head
drawSnakeCell(head_x, head_y);
return 2;
}
matrix[head_y][head_x] = 219; // add head
drawSnakeCell(head_x, head_y);
return 0;
}
int1 refreshSnakeDir() {
unsigned int8 oldDir;
oldDir = snake_dir;
if(keyUpPressed) snake_dir = 0;
if(keyRightPressed) snake_dir = 1;
if(keyDownPressed) snake_dir = 2;
if(keyLeftPressed) snake_dir = 3;
if(oldDir!=snake_dir)
return 1;
else
return 0;
}
void main() {
unsigned int8 i;
unsigned int8 res;
unsigned int1 dirChanged;
glcd_clear();
matrix_clear();
snake_y[0] = 0;
snake_y[1] = 0;
snake_y[2] = 0;
snake_x[0] = 2;
snake_x[1] = 1;
snake_x[2] = 0;
matrix[0][0] = 219;
matrix[0][1] = 219;
matrix[0][2] = 219;
drawSnakeCell(0, 0);
drawSnakeCell(1, 0);
drawSnakeCell(2, 0);
put_food();
while(true) {
for(i=0; i<4; i++) {
dirChanged = refreshSnakeDir();
delay_ms(50);
dirChanged |= refreshSnakeDir();
delay_ms(50);
dirChanged |= refreshSnakeDir();
delay_ms(50);
dirChanged |= refreshSnakeDir();
delay_ms(50);
dirChanged |= refreshSnakeDir();
if( dirChanged || keyBPressed || keyAPressed )
break;
}
if(keyBPressed) // exit app
reset_cpu();
refreshSnakeDir();
res = move_snake();
if(res==2) {
score++;
put_food();
}
if(res==-1) {
glcd_clear();
glcd_putc("Game Over\r\nscore = ");
glcd_putn(score);
delay_ms(1000);
reset_cpu();
}
}
}
Subscribe to:
Posts (Atom)