Showing posts with label ATMega328. Show all posts
Showing posts with label ATMega328. Show all posts

Sunday, 26 April 2015

Atmega 328/Uno simple Dub synth

R2R DAC -view picture in the end of article. Usa same principle to build an 8 Bit R2R DAC from D0 to D7


Some intial test sounds out of a Uno mini Dub synth. The file was  recorded , unfiltered ( 0 to 5V) and lined out of a guitar amp in clean mode. - Some noise was introduced by the guitar amd as well.
Next step of project is to AC couple signal also with a suitable RC filter, decoupling capacitors and prepare the rest of line out for use with sound gear.
The limitations of the ATMega328 are big compared to the DUE for this kind of project, but good enough to get some interesting sounds, plus it can also double as a dub siren . Sr @ 16kHz-8Bit Dac

You can download /preview  it in mp3 here


a 6 bit R2R Dac


Tuesday, 14 April 2015

ARDUINO IDE 1.6.3 RELEASED

A new version of the Arduino IDE (1.6.3) is available at the download page!
The Arduino IDE 1.6.3 is a bug fix release: after the already released 1.6.2 with new libraries and cores managers.http://blog.arduino.cc/2015/04/02/arduino-ide-1-6-3-released-and-available-for-download/

Friday, 5 September 2014

Example Saw waveform generator with R2R DAC ATmega328

/*
Example Saw waveform generator with 8 bit R2R DAC pin 0-7
Timer1 Interrupt
*/

#define WAVE_SAMPLES 256
volatile uint16_t a;
uint8_t sample = 0;
boolean c;
boolean togg;
int timer1_counter;

void setup()
{
  DDRD = 0xFF; //b11111111 d255

  // initialize timer1
  cli();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;

  // Set timer1_counter to the correct value for our interrupt interval
  timer1_counter = 65443;   // preload timer 65536-16MHz/8/21504 Hz

  TCNT1 = timer1_counter;   // preload timer
  TCCR1B |= (1 << CS11);    // clk/8 prescaler
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  sei();          // enable all interrupts
}

ISR(TIMER1_OVF_vect)        // interrupt service routine
{
  TCNT1 = timer1_counter;   // preload timer
  PORTD = sample;
  togg = !togg;
}

void loop()
{
  if (c != togg) {
    a++;
    if (a >= WAVE_SAMPLES) {
      a =0;
    }
    sample =a;
  } //
  c = togg;
}

Friday, 20 July 2012

12 bits Digital to analog (DAC) MCP4725: variable (basic)sample


A ramp up                      
A round sine                          


#include <Wire.h>
#include <util/delay.h>
// Device = 96;  This hardwired into the IC and the BoB, in other words, it is a given.
#define MCP4725_DID 96 // define device id - see datasheet
int sample = 0 ; //sample variable
int OOMPH[64] = {
  2, 2, 22, 61, 119, 196, 291, 402, 530, 672, 827, 994, 1172,
  1357, 1549, 1747, 1947, 2147, 2347, 2545, 2737, 2922, 3100, 3267, 3422, 3564, 3692, 3803,
  3898, 3975, 4033, 4072, 4092, 4092, 4072, 4033, 3975, 3898, 3803,
  3692, 3564, 3422, 3267, 3100, 2922, 2737, 2545, 2347, 2147, 1947,
  1747, 1549, 1357, 1172, 994, 827, 672, 530, 402, 291, 196, 119, 61,
  22, } 
;
/* uncomment to use */
/* int sintab [64] = {
 2147 , 2347, 2545, 2737, 2922, 3100, 3267, 3422, 3564, 3692, 3803,
 3898, 3975, 4033, 4072, 4092, 4092, 4072, 4033, 3975, 3898, 3803,
 3692, 3564, 3422, 3267, 3100, 2922, 2737, 2545, 2347, 2147, 1947,
 1747, 1549, 1357, 1172, 994, 827, 672, 530, 402, 291, 196, 119, 61,
 22, 2, 2, 22, 61, 119, 196, 291, 402, 530, 672, 827, 994, 1172,
 1357, 1549, 1747, 1947} ;*/

/* int ramp_up [64] = { 
 2347, 2545, 2737, 2922, 3100, 3267, 3422, 3564, 3692, 3803,
 3898, 3975, 4033, 4072, 4092, 2, 22, 61, 119, 196, 
 291, 402, 530, 672, 827, 994, 1172, 1357, 1549, 1747, 
 1947, 2347, 2545, 2737, 2922, 3100, 3267, 3422, 3564, 3692, 
 3803, 3898, 3975, 4033, 4072, 4092, 2, 22, 61, 119, 
 196, 291, 402, 530, 672, 827, 994, 1172, 1357, 1549, 
 1747, 1947, 2347, 2545 } ; */
void setup()
{
  int potRead = 0; //potentiometer read in pin Analog 0
  long potValue ; //value for potentiometer read 
  pinMode (potRead, INPUT);
  Wire.begin() ;
} 


void loop()
{
  int potRead = 0;     //potentiometer read in pin Analog 0
  long potValue ;     //value for potentiometer read 
  potValue = analogRead(potRead);
  //we map amalog 0-1023/1-19000 for DAC:
  potValue = map(analogRead(potRead), 0, 1023, 1, 19000); 
  // Start transmission
  Wire.beginTransmission(MCP4725_DID); //device adress
  Wire.write(64);                     // cmd to update the DAC
  Wire.write(OOMPH[sample] >> 4);        // the 8 most significant bits...
  Wire.write((OOMPH[sample] & 15) << 4); /* the 4 least significant bis...*/
  Wire.endTransmission();
  sample = (sample + 1) &63 ;
  _delay_us(potValue); // delay 30 ms, acording to <util/delay.h
}





Simple siren generator for Arduino.

This is a simple siren generator, as mentioned.
We will only improve on this...
Graphics and schematic by Fritzing (http://fritzing.org/ )


/*
 * Siren Generator with adjustable rate
 * Version 0.1
 * Author: Ras B / Keith Gray 
 * Created: 3/5/12
 */
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int SPKR_PIN = 10; //assigning pin 10 to the speaker
const int MAX_FREQ = 10000; //max frequency of the siren wail
const int MIN_FREQ = 3700; //min frequency of the siren wail

int potRead = 0; //potentiometer read in pin Analog 0
int potValue ; //value for potentiometer read 
int FREQ_SKIP ; //frequency skip variable
int DELAY = potValue; // variable for delay linking it to the potValue variable

void setup()
{
  pinMode(SPKR_PIN, OUTPUT);
  pinMode (potRead, INPUT);

  updateDisplay();
  updatefreqSkip();
}
void updateDisplay() //creating a function we can call that updates the LCD
{
  lcd.clear();
  // adding some name to the values we want to display:
  lcd.print("Rate=");
  // calling the values we want to display:
  lcd.print(potValue);
  lcd.print(" Freq=");
  // Print the value of the frequency skip
  lcd.print(FREQ_SKIP);
}

void updatefreqSkip() //creating a function we can call that updates the FREQ_SKIP
{
  if (potValue >= 8)
  { 
    FREQ_SKIP = 10 ;
  }
  else
  {
    FREQ_SKIP = 30 ;
  }
}


void loop()
{
  updatefreqSkip();

  potValue = analogRead(potRead);
  potValue = map(analogRead(potRead), 0, 1023, 0, 10);

  updateDisplay();

  unsigned long siren_start_time = millis();
  int freq;
  updatefreqSkip();
  updateDisplay();
  do
  {
    for (freq=MIN_FREQ; freq<=MAX_FREQ; freq+=FREQ_SKIP)
    {
      analogRead(potRead);
      DELAY = potValue;
      tone(SPKR_PIN, freq);
      delay(DELAY);
    }
    updateDisplay();
    updatefreqSkip();

    for (freq=MAX_FREQ; freq>=MIN_FREQ; freq-=FREQ_SKIP)
    {
      analogRead(potRead);
      DELAY = potValue;
      tone(SPKR_PIN, freq);
      delay(DELAY);
    }
    updateDisplay();
    updatefreqSkip();
  }
  while (millis() - siren_start_time < 5000L);
}


Sunday, 1 July 2012

AVR- Intro to I/O ports in C Language instead of Arduino/Processing Language - (...Cont)


Now lets imagine we need only some of the ports as inputs, the rest as outputs.
Lets assume the port D pins 0-4 to be defined as outputs, the remaining pins 5-7 will function as inputs. For this purpose it is necessary to enter in the port D data direction registers DDRD the following bit configuration :


// as defined in included avr/io.h DDRD  
# include <avr/io.h>
 
int main ( ) 
{ 
  // Set the bits 0,1,2,3 and 4 
  // binary hexadecimal 1F = 00011111 preceded by 0x as stated before
  DDRD = 0x1F;    
 
  // Clear alternative in binary system would be
  // DDRD = 0b00011111;
 
  // Full notation: identical functionality, more typing
  // But clear and self-explanatory:
  // DDRD = (1 << DDD0) | (1 << DDD1) | (1 << DDD2) | (1 << DDD3) | (1 << DDD4); */


So , Maybe now is time to mention something else. We dont necessarily need to refer to the 
pins always through the whole port. As you can probably notice in the last alternative 
example above, you can also use DDD1 or DDB1 if it were in the Port B; PDx, and PINDx, DDDx for the port D or maybe simpler would be also PAx, PBx, PCx, etc... For the compiler
, the expressions (1 << PD5), (1 << DDD5) and (1 << PIND5) are identical to (1 << 5) 
(more precisely, the preprocessor replaces the expressions (1 << PC7). to .(1 << 7)).
All this is specified in the file io.h of the avr-libc and serves only to improve code readability. *(Check last example in this post for a practical example of code)
You can always check also the file iom328p.h under /* Registers and associated bit numbers */ for a better clarification ( or the file corresponding to the chip you might be using).




So , now, lets look at other examples based on these options :  

...
   // All pins of Port D defined as outputs:
  DDRD = 0xff; 
  // Pin0 again left as input and the rest in their original state: 
  DDRD &= ~ ( 1 << DDB0 ) ,
   // pin 3 and 4 as inputs and the rest in their original state:  
  DDRD &= ~ ( ( 1 << DDB3 ) | ( 1 << DDB4 ) ) ,
   // pin 0 and 3 as outputs and rest in their original state: 
  DDRD |= ( 1 << DDB0 ) | ( 1 << DDB3 ) ;
   // All input pins: 
  DDRD = 0x00;

...

So based on what we have learned until now, lets set the pin 5 of port D to output

// as defined in included avr/io.h DDRD : 
# include <avr/io.h>
 
...
    PORTD = 0x10; /* better would have been PORTD = (1 << PD4) */
 
    // Clear alternative would be binary notation 
    PORTD = 0b00010000;     /* direct assignment - clear */
   

PS: Note that the bits are always to be counted from 0 , so the least significant bit is 
bit number 0, not number 1 bit .
So now lets imagine we need to change an output pin, but want to leave the rest unchanged ( see next tutorial "Introduction to C language bitwise operators and relevant truth tables". )

/* as defined in included avr/io.h DDRD : */
# Include <avr/io.h>
...
    PORTD = PORTD | 0x10; /* better would be : PORTD = PORTD | (1 << PD5) */ 
    /* simplified by using the | = operator: */ 
    PORTD | = ( 1 << PD5 ) ;
 
    /* Also several pins "simultaneous": */ 
    PORTD | = ( 1 << PD4 ) | ( 1 << PD5 ) ; /* pins PD4 and PD5  "high" */

Turn those same pins to LOW is somewhat analogous
/* as defined in included avr/io.h DDRD : */
# include <avr/io.h>
...
    PORTB & = ~ ( 1 << PB2 ) ;  /* delete Bit 2 and thus sets pin PB2 in PORTB  to low */
    PORTB & = ~ (  ( 1 << PB4 ) | ( 1 << PB5 )  ) , /* Pins PB4 and PB5  pin "low" */

Now, we should also note the fact that If the initial state of outputs is critical, the sequence must be noted at which the data direction (DDRx) is set and the output value (PORTx) set:
For output pins, which are to be initialized "HIGH" with initial value:
  • First, the bits in the register set PORTx
  • then set the data direction to output
Hence the sequence obtained for a pin that was previously configured as input with pull-up switched off:
  • set PORTx: active internal pull-up
  • DDRx set: output ("high")
In the first sequence DDRx and then  PORTx there may be a short "low pulse", and cause  the external pull-up resistors to be bypassed. The (unfavorable) sequence: input -> set DDRx : output ( on "low" because of PORTx after reset 0) -> set PORTx: output to high. As this might come to influence your design ( or not ) I would advise you to check the datasheet section Configuring the Pin on page 78 ( english version) 
http://www.atmel.com/Images/doc8161.pdf .

#include <avr/io.h>
#include <util/delay.h>
int main(void)         // For now we are just going to turn a led on */

{
  DDRB = 0b00100000;   // Data Direction Register setting pin0 to output and the remaining pins as input
  while(1)
  {
    PORTB = 0b00100000 ; // Set pin PB5 = pin13 no Arduino Uno to 5 volts
    _delay_ms (1000);
   PORTB = 0b00000000 ;
    _delay_ms (1000);
  }

  // * Never reached * /
  return  0 ;
}
or another way would be

#include <avr/io.h>
#include <util/delay.h>
int main(void)// For now we are just going to turn a led on */ {  DDRB = 0b00100000;   // Data Direction Register setting pin0 to output and the remaining pins as input
  while(1)
  {
    PORTB = 0b00100000; 
    _delay_ms (1000);
    PORTB = 0b00000000; 
    _delay_ms (1000);
    // Code would be in here if needed to execute over and over and over ... endlessly */
  }
  // * Never reached * /
  return  0 ;
}
That is all for now, i hope this will have helped you to understand better the intricacies 
of the AVR C with AVR GCC !
PS- this is in no way a detailed ultimate tutorial, but more the result of my understanding of it !! 
So dont take my word for definite as there will be things to add, and more things
that i havent even touched . Remember i come from the Arduino perspective, and 
for now just wanna deepen my knowledge, so i can pass to AVR GCC when ready !



Reference



http://elecrom.wordpress.com/2008/02/12/avr-tutorial-2-avr-input-output/

http://www.nongnu.org/avr-libc/user-manual/modules.html

http://www.mikrocontroller.net/articles/AVR-Tutorial ( Assembler, in German
but a lot of info to be dranked from here !

...too much time on my hands?

WHAT ?!? What do u mean i have too much time on my hands? Lol






Tuesday, 26 June 2012

DIY DUBSIREN Kits (test PCB Boards)

My test PCB Boards( without ground plane, as they only test boards) just arrived...
So, after my tests, we will finally have available soon the DIY DUBSIREN Kits available !! 2 Diff models !! Nuff works happening !!