AdSense

Monday, 17 February 2014

A free tool to draw circuits

(Deutsche Version) Today, I want to refer to a useful program:
TinyCAD
With this program, you can draw circuits on a very easy level and export them as an image. You do not need to create an account or anything like that. The program is very simple and does exactly what you want so you do not need to take 100 tutorials to being able to draw a simple circuit.

Control LED strip with ATmega / Arduino

(Deutsche Version) LED strips have been gaining more and more popularity within the last few years. There are even LED strips for less than 20 euro from china. Usually, an LED strip consists of a control unit, a power supply and a remote. For most people, this is sufficient. Anyone who wants to have more (e.g. run through sequences) has to put in a little effort.

Let's primarily face the structure of the strip. There are four connections, one of them is for the + 12 V power supply, the other three connections are for the individual colours. The strip is working like this: If you apply + 12 V and then connect ground to one of the colour connections, this colour is shining. The brightness is now controlled vie PWM. To fully control the LED strip you need:
  • A microcontroller (ATmega / Arduino)
  • 3 bipolar transistors (NPN) which can handle enough current!
The microcontroller sends 3 PWM signals to the base of the transistors (apply pre-resistors, I use 470 Ohms). The emitter of the transistors is connected to ground (a common ground of the 12 V power supply and the microcontroller), the collector is connected to the corresponding colour channel.

To control a single color, you have to execute:


analogWrite(8, 127);

This command will set the transistor which is connected to pin 8 to 50% (255 is the maximum), so the connected colour has 50% brightness. You can only use PWM channels for this (in the data sheet usually referred as OCR).


To achieve any color, you have to mix the colors. therefore, you have to choose a colour in the RGB space, e.g. orange: this colour is R: 255, G:255, B:0. Now you have to program this into the microcontroller:


analogWrite(RED_PIN, 255);
analogWrite(GREEN_PIN, 255);
analogWrite(BLUE_PIN, 0);  

It could occur that different colours are seen at different brightness, you should test this and then set the maximum limit e.g. for green to 127 (green appears very bright for the human eye, therefore the green colour could be too bright.

Sunday, 16 February 2014

"Home Automation" with Arduino and 433 MHz - The complete remote control

(Deutsche Version) I finally merged the control for my shutters and the power outlet into one program and built a small remote control.


Hardware

There is not much to say about the hardware:

It's an Attiny44A, a pullup resistor for the RESET-pin, three buttons (up, down, stopp), a button cell holder and the 433Mhz transmitter. Each button is connected toan input of the Attiny. If the button is triggered, the input is pulled to ground.

Software

The functions for controlling the shutters and the power outlet have been explained in my other posts (unfortunately at the moment these posts are only available in german), so I'm not going to explain the following source code in detail.

#include <RCSwitch.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

RCSwitch mySwitch = RCSwitch();
unsigned char buttonDown = 10;
unsigned char buttonStopp = 9;
unsigned char buttonUp = 7;
unsigned char buttonPressed = 0;

char stopRequest = 0;

void setup() {
  //disable interrupts
  cli();

  //initialize pins
  pinMode(buttonDown, INPUT_PULLUP);
  pinMode(buttonStopp, INPUT_PULLUP);
  pinMode(buttonUp, INPUT_PULLUP);

  //initialize transmitter and switch off power outlet
  mySwitch.enableTransmit(0);  //transmitter is connected to pin 0
  mySwitch.setProtocol(1);
  mySwitch.switchOff("11011", "10000");

  //save energy!
  ADCSRA &= ~(1<<ADEN); //disable ADC
  ACSR = (1<<ACD); //disable Analog Comparator

  //initialize Pin-Change-Interrupt
  PCMSK1 |= (1<<PCINT8); //Pin-Change-Interrupt at pin 2 (Arduino Pin  10)
  PCMSK1 |= (1<<PCINT9); //Pin-Change-Interrupt at pin 3 (Arduino Pin 9)
  PCMSK0 |= (1<<PCINT7); //Pin-Change-Interrupt at pin 6 (Arduino Pin 7)
 
  //prepare Power-Down-Mode
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  //enable interrupts
  sei();
}
void loop() {
  sendCommand();
  powerDown();
} 

void sendCommand() {
  if (buttonPressed == buttonDown) {
    mySwitch.switchOn("11011", "10000");
    delay(750);
    sendCommandDown();
    powerDown(25);
    mySwitch.switchOff("11011", "10000");
    buttonPressed = 0;
  }

  else if (buttonPressed == buttonUp) {
    mySwitch.switchOn("11011", "10000");
    delay(750);
    sendCommandUp();
    powerDown(25);
    mySwitch.switchOff("11011", "10000");
    buttonPressed = 0;
  }
}

//command shutters up
void sendCommandUp() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100F0F0F");
  mySwitch.sendQuadState("0F0F0100QQ0F100F0F1Q");
  mySwitch.setProtocol(1);
}

//command shutters stopp
void sendCommandStopp() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100FFFFF");
  mySwitch.setProtocol(1);
}

//command shutters down
void sendCommandDown() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100F0101");
  mySwitch.sendQuadState("0F0F0100QQ0F100F0110");
  mySwitch.setProtocol(1);
}

//let Attiny wait for time secinds
void powerDown(char time) {
  GIMSK |= (1<<PCIE1); //enable Pin-Change-Interrupt
  GIMSK |= (1<<PCIE0);
  
  stopRequest = 0;

  for (char i = 1; i<= time*1000; i++) {
    if (stopRequest == 0) {
      delay(1);
    }
  }

  GIMSK &= ~(1<<PCIE1); // disable Pin-Change-Interrupt
  GIMSK &= ~(1<<PCIE0);
}

//set Attiny to Powerdown-Mode until Pin-Change-Interrupt
void powerDown() {
  GIMSK |= (1<<PCIE1); //enable Pin-Change-Interrupt
  GIMSK |= (1<<PCIE0);
  sleep_mode();  //go to sleep
  //software will continue here after leaving sleep mode
  GIMSK &= ~(1<<PCIE1); //disable Pin-Change-Interrupt
  GIMSK &= ~(1<<PCIE0);
}

void checkButton() {
  if (digitalRead(buttonDown) == LOW) {
    buttonPressed = buttonDown;
  }

  else if (digitalRead(buttonStopp) == LOW) {
    stopRequest = 1;
    mySwitch.switchOff("11011", "10000");
  }

  else if (digitalRead(buttonUp) == LOW) {
    buttonPressed = buttonUp;
  }
}

//ISR for PCINT1 and PCINT0 (Pin-Change-Interrupts)
ISR(PCINT1_vect)
{
  checkButton();
} 
ISR(PCINT0_vect)
{
  checkButton();
} 


The remote control is powered by a CR2032 button cell, so the amount of available energy is limited. Since the control isn't doing anything 99.999% of the time, the Attiny enters sleep mode using the powerdown() function. It sleeps until a button is triggered (Pin-Change-Interrupt). To save as much energy as possible, ADC and AC are switched off.

Sunday, 27 October 2013

Arduino-Code on the ATmega 1284P

(Deutsche Version) Running Arduino code on an ATmega 1284P is pretty simple. You only have to execute some small steps. At first, you have to download the following archive:
https://github.com/maniacbug/mighty-1284p/zipball/master
The content has to be extracted to C:\Program Files (x86)\Arduino\hardware\mighty-1284p (respectively the location where you installed the development environment). Afterwards, the development environment has to be restarted. Now, the 1284 can already be selected. I use the Original Mighty 1284p 16MHz. The pin mapping is different, see below (The number in the Parentheses  is relevant for the Arduino):

                      +---\/---+
           (D 0) PB0 1|        |40 PA0 (AI 0 / D24)
           (D 1) PB1 2|        |39 PA1 (AI 1 / D25)
      INT2 (D 2) PB2 3|        |38 PA2 (AI 2 / D26)
       PWM (D 3) PB3 4|        |37 PA3 (AI 3 / D27)
    PWM/SS (D 4) PB4 5|        |36 PA4 (AI 4 / D28)
      MOSI (D 5) PB5 6|        |35 PA5 (AI 5 / D29)
  PWM/MISO (D 6) PB6 7|        |34 PA6 (AI 6 / D30)
   PWM/SCK (D 7) PB7 8|        |33 PA7 (AI 7 / D31)
                 RST 9|        |32 AREF
                VCC 10|        |31 GND
                GND 11|        |30 AVCC
              XTAL2 12|        |29 PC7 (D 23)
              XTAL1 13|        |28 PC6 (D 22)
      RX0 (D 8) PD0 14|        |27 PC5 (D 21) TDI
      TX0 (D 9) PD1 15|        |26 PC4 (D 20) TDO
RX1/INT0 (D 10) PD2 16|        |25 PC3 (D 19) TMS
TX1/INT1 (D 11) PD3 17|        |24 PC2 (D 18) TCK
     PWM (D 12) PD4 18|        |23 PC1 (D 17) SDA
     PWM (D 13) PD5 19|        |22 PC0 (D 16) SCL
     PWM (D 14) PD6 20|        |21 PD7 (D 15) PWM
                      +--------+

Thursday, 24 October 2013

Control RGB LED with ATmega16A

(Deutsche Version) RGB LEDs are pretty interesting (e.g. if they are in an LED strip). Today, I want to explain how to control an RGB LED with an ATmega16A. At first a short introduction to the RGB LED: I use this LED from Tayda Electronics. This LED consists of three different LEDs which are all in the same body. Therefore, there are 3 pins for the different LEDs and a common cathode (-). If you apply a PWM signal to these 3 pins, you can control the color of the LED. I use the ATmega16A because the ATmega8 only has 2 PWM channels, this is not enough for 3 pins. This should cover the basics for an RGB LED, here is the code which runs through the whole colour space:

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

int main(void)
{
  DDRA = 0xFF;//Output
  DDRD = 0xFF;
  ICR1 = 256;
  TCCR2 = (1<<WGM20) | (1<<COM21) | (1<<CS20); // PWM, phase correct, 8 bit.
  TCCR1A = (1<<WGM10) | (1<<COM1A1) | (1<<COM1B1); // PWM, phase correct, 8 bit.
  TCCR1B = (1<<CS10);// | (1<<CS10); // Prescaler 64 = Enable counter, sets the frequency
  double rCounter = 255;
  double rMax=255;
  double bCounter = 255;
  double bMax = 180;
  double gCounter = 0;
  double gMax = 70;
  int stages = 0;
  while(1)
  {
    switch (stages)
 {
   case 0:
     bCounter --;
     if (bCounter <= 0)
  {
    stages = 1;
  }
  break;
      case 1:
     gCounter ++;
     if (gCounter >= 255)
  {
    stages = 2;
  }
  break;
   case 2:
     rCounter --;
     if (rCounter <= 0)
  {
    stages = 3;
  }
  break;
   case 3:
     bCounter ++;
     if (bCounter >= 255)
  {
    stages = 4;
  }
  break;
   case 4:
     gCounter --;
     if (gCounter <= 0)
  {
    stages = 5;
  }
  break;
   case 5:
     rCounter ++;
     if (rCounter >= 255)
  {
    stages = 0;
  }
  break;
 }
 OCR1B = (int)(bCounter*bMax*bCounter/255/255);
 OCR1A = (int)(gCounter*gMax*gCounter/255/255);
 OCR2 = (int)(rCounter*rMax*rCounter/255/255);

 _delay_ms(5);
  }

}

Tuesday, 8 October 2013

C# - List all files in folder and sub folders

(Deutsche Version) Reading all files in a folder is pretty simple (see also C# Tipps and Tricks). If you want to do this recursively, the solution is also simple. The code I therefore use is the following:

var allfiles = System.IO.Directory.GetFiles(
  @"C:\YourFolder",  
  "*.*"
  System.IO.SearchOption.AllDirectories);

foreach (string file in allfiles) {}

To filter this result, you can add a .Where at the end, the following code will only list audio files:

var allfiles = System.IO.Directory.GetFiles( 
  @"C:\YourFolder"
  "*.*"
  System.IO.SearchOption.AllDirectories).Where(
    s => s.EndsWith(".mp3") || 
    s.EndsWith(".wav") || 
    s.EndsWith(".wma"));  

foreach (string file in allfiles) {}

Monday, 7 October 2013

LCD Display with Arduino / ATmega

(Deutsche Version) I bought this LCD module and this I2C controller. In this post, I will explain how to display text on the display. At first, you need the LiquidCrystal_I2C library from here. (I took the newest Version). Now you can directly start in the Arduino development enviroment. At first the includes:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

Next, you have to define several things which are (in the library) not suitable for my LCD module:

#define I2C_ADDR    0x20

#define BACKLIGHT_PIN  3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

#define  LED_OFF  1
#define  LED_ON  0

Now you have to define the display:

LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

Next, you can start in the setup()-function. At first, you have to tell the program what kind of display you have (the size, I have a 20 x 4 character display).

  lcd.begin (20,4);
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(LED_ON);

The rest is needed if you want to switch on the backlight with lcd.backlight();. Afterwards, the display is resetted:

  lcd.clear();
  delay(1000);
  lcd.home();

Now you can write things onto the display:

  lcd.print("Hello, world!");

To place the cursor at a specified position, you have to do the following:

  lcd.setCursor(5,1);

This should cover all basic functions. To delete everything, simply call lcd.clear(); .

A small hint, this problem took some time for me to solve: If you program an ATmega and then plug it into a pin board, usually nothing works, the ATmega needs a reset after it is plugged into the pin board. This could be caused by the fact that the ATmega already starts running when only some pins are connected to the pin board.