Forum Index > General > Ask an Evil Mad Scientist!
 Requesting help porting C code into Arduino
 |  Printable Version
By: Anonymous: Jeff Haas () on Thursday, August 25 2011 @ 08:09 PM PDT (Read 4915 times)  
Anonymous: Jeff Haas

I got some help from a friend on a microcontroller project, he did a lot of work, but just started a new job and doesn't have time to do the final step. He coded in C on an Atmega chip (with no Arduino bootloader, because it was easier for him) and I have the code, but there are some differences between what he did and what works in the Arduino environment.

The project is for Halloween: It's a geiger counter sound generator. I looked around on the web and all I could find was .wav files. This project generates a live clicking sound, which varies in rate, and also uses an LM386 to drive an 8 ohm speaker. I've bought a Diavolino for the final build, but the port from C is a bit beyond me at this point.

Is there someone who would be willing to look at the code and help convert it? I plan on sharing the final project on Instructables, so others can make their own mad scientest labs and creep people out this year.

Jeff






       
   
By: Windell (offline) on Thursday, August 25 2011 @ 11:34 PM PDT  
Windell

Why do you need to do any conversion? The Arduino is essentially an Atmega development board with a brand name on it-- if it works on an ATmega328, it will still run on the Arduino, whether or not you do any conversion.


Windell H. Oskay
drwho(at)evilmadscientist.com
http://www.evilmadscientist.com/

Forum Evil Scientist
Evil Scientist

Status: offline

Registered: 06/15/06
Posts: 1932
Sunnyvale, CA

Profile Email Website  
   
By: Anonymous: linxdev () on Friday, August 26 2011 @ 06:53 AM PDT  
Anonymous: linxdev

Quote by: Windell

Why do you need to do any conversion? The Arduino is essentially an Atmega development board with a brand name on it-- if it works on an ATmega328, it will still run on the Arduino, whether or not you do any conversion.



The issue may be that it does not work well in the IDE. The IDE does things that will make a compile of code written outside fail.

I would be willing to put the code on my Linux system and do a test compile and upload. I do ALL my development now in an Xterm on the CLI. That is what I prefer.

I would also suggest not trying to load this u[p on something like an UNO unless you do convert it to use the Arduino APIs.

Build the Diavolino and get yourself an AVRISP programmer.





       
   
By: Anonymous: Jeff Haas () on Friday, August 26 2011 @ 08:56 AM PDT  
Anonymous: Jeff Haas

Linxdev is right - the code doesn't work in the IDE, and I was hoping to be able to tweak it and add a few features, use the IDE to download it, etc. I have a couple of regular Arduinos and just built a Diavolino, and was hoping not to have to get another piece of hardware for this project.

I appreciate the help and advice. Here's the code:

PHP Formatted Code
/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <joerg@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.        Joerg Wunsch
 * ----------------------------------------------------------------------------
 *
 * Simple AVR demonstration.  Controls a LED that can be directly
 * connected from OC1/OC1A to GND.  The brightness of the LED is
 * controlled with the PWM.  After each period of the PWM, the PWM
 * value is either incremented or decremented, that's all.
 *
 * $Id: group__demo__project.html,v 1.1.1.17 2008/11/06 22:24:49 joerg_wunsch Exp $
 */

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <stdlib.h>
#include "iocompat2.h"
#include "pin_macros.h"

#define INIT_TIMER_COMP 0xffff

#define LOWBYTE(val)  ((uint8_t)((val) & 0xff))
#define HIGHBYTE(val) ((uint8_t)(((val) & 0xff00) >> 8))

#define B_DATA_PORT_MASK (_BV(DDB0) | _BV(DDB1)) /* b1:0 output */

#define D_DATA_PORT_MASK (_BV(DDD2) | _BV(DDD3) | _BV(DDD4) | _BV(DDD5) | _BV(DDD6) | _BV(DDD7))  /* b7:2 output */

int foo(void) {
    return 2;
}
enum { UP, DOWN };

void toggle_b2(void)
{
    PORTB ^= _BV(PORTB2);
}

void led_out (uint8_t val)
{
    unsigned char bval;
    unsigned char dval;

    val = ~val;

    bval = PORTB & ~(B_DATA_PORT_MASK);
    dval = PORTD & ~(D_DATA_PORT_MASK);

    bval |= (val & B_DATA_PORT_MASK);
    dval |= (val & D_DATA_PORT_MASK);

    PORTB = bval;
    PORTD = dval;

}
void stop_timer1 (void)
{
    TCCR1B = TCCR1B & ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
}
void start_timer1 (void)
{

    TCCR1B |=    _BV(WGM12); /* Put Timer 1 into CTC mode (Clear time on Compare match) */
   
    TCCR1B |= _BV(CS11); /* clock prescale divide by 8 */

}

ISR (TIMER1_OVF_vect)
{
    led_out(0x1);
}
void set_compare_timer1 (uint16_t val)
{
    OCR1AH = HIGHBYTE(val);
    OCR1AL = LOWBYTE(val);
}
#define INITSHIFT 3
int sit = (50<<INITSHIFT);
int shift = INITSHIFT;
ISR (TIMER1_COMPA_vect)
{
//    static char x = 0;
//    static char y = 0xff;
    static unsigned int delay = 0;

    cli();
    stop_timer1();
    toggle_b2();
    delay = (rand() & 0xffff);
    if (delay < 0x40) {
        delay = 0x40;
    }
   
    if (sit-- <= 0) {
        shift--;
        if (shift < 0) {
            shift = (INITSHIFT);
        }
        sit = (50<<INITSHIFT);
    }
   
    set_compare_timer1(delay>>shift);
    start_timer1();

    led_out(shift);
#if defined (NOTUSED)  
   if (!x) {
        led_out(0x2);
        x=1;
    } else {
        y = ~y;
        led_out(y);
    }
#endif

    sei();
}

void
ioinit (void)
{

    DDRB = B_DATA_PORT_MASK | _BV(DDB2); /*  b2 toggle val */
    DDRD = D_DATA_PORT_MASK;

    PORTB = 0;
    PORTD = 0;

    TCCR1A = 0;
    TCCR1B = 0;

    /* set compare register OCR1A to max until first intr */
//    set_compare_timer1(INIT_TIMER_COMP);
    set_compare_timer1(0x4000);


    TCCR1A = 0;


    /* Start clock */
//    TCCR1B |=  _BV(CS10) | _BV(CS12); /* divide by 1024 clock prescaler */

    TCCR1B |=    _BV(WGM12); /* Put Timer 1 into CTC mode (Clear time on Compare match) */
   

    TCCR1B |= _BV(CS11); /* clock prescale divide by 8 */



}
#define JVAL 100000;
int
main (void)
{

    //    int i;
//    long j = JVAL;

    ioinit ();

    srandom(0x12345678L);
    set_sleep_mode(SLEEP_MODE_IDLE);

    TIMSK1 = _BV (OCIE1A);
    cli();

    sei ();


//    for (;;) {
//      if (j-- <= 0) {
//          j = JVAL;
//          i = rand();
//          PORTB = (unsigned char) (i & DDRB);
//          PORTD = (unsigned char) (i & DDRD);
//      }
//    }

    sleep_enable();
    sei();
    /* loop forever, the interrupts are doing the rest */
    for (;;) {
       
        sleep_cpu();
    }
    return (0);
}





       
   
By: Anonymous: linxdev () on Friday, August 26 2011 @ 09:07 AM PDT  
Anonymous: linxdev

PHP Formatted Code

tmp/h.cpp:36:23: error: iocompat2.h: No such file or directory
tmp/h.cpp:37:24: error: pin_macros.h: No such file or directory
 



Here is a better idea. Respond with the feature(s) you need. This program is short enough that the Arduino API can handle this.

I'll see what I can come up with.





       
   
By: Anonymous: Jeff Haas () on Friday, August 26 2011 @ 10:54 AM PDT  
Anonymous: Jeff Haas

Thank you! That is much more than I expected.

Overall, I would like to be able to paste this code into the Arduino IDE and be able to download it to a board. What the code does is to make a geiger counter-like clicking sound. The output to one of the pins is toggled on and off in a randomized pattern, and there's also code to speed up and slow down how fast it goes. If you just connect the pin to an 8-ohm speaker, it's not very loud, so we're using an LM386 to drive the speaker.

I tried this in the Arduino IDE, saw that there were a couple of libraries that weren't the same (the ones you showed), and also saw that some of the pin definitions seem to be different. Such as, #define B_DATA_PORT_MASK (_BV(DDB0) | _BV(DDB1)) /* b1:0 output */

He also set up a second output for an LED so the sound is visualized.

I'd like to be able to add a PIR so that this wouldn't make noise constantly, but would only come on when motion is detected. I've done this before and triggered relays using an Arduino so I'm pretty sure I can handle it here.

But the first step is getting this so I can download it and try it out. Thank you again!

Jeff





       
   
By: Windell (offline) on Friday, August 26 2011 @ 11:40 AM PDT  
Windell

You're not alone. I write most of my "Arduino" code by writing AVR-GCC code, and then copy-pasting everything before the main loop into setup, and the main loop into loop. Cool

I have a couple of regular Arduinos and just built a Diavolino, and was hoping not to have to get another piece of hardware for this project.

You *do not* have to get more hardware to use the ISP programming method-- you can actually use one Arduino as an ISP programmer. See here, and/or pick up our ISP shield if you only want to get *a little bit* of new hardware. Big Grin


Windell H. Oskay
drwho(at)evilmadscientist.com
http://www.evilmadscientist.com/

Forum Evil Scientist
Evil Scientist

Status: offline

Registered: 06/15/06
Posts: 1932
Sunnyvale, CA

Profile Email Website  
   
By: Windell (offline) on Friday, August 26 2011 @ 12:24 PM PDT  
Windell

So... I copied and pasted your code into the Arduino IDE. It didn't compile because of these two lines:

PHP Formatted Code
#include "iocompat2.h"
#include "pin_macros.h"



But, so far as I can tell, you weren't actually using anything from those header files. If you comment out those two lines, the program compiles, and uploads to an Arduino-- just fine. I haven't checked to see if the program is doing what it's supposed to, but it sure as heck doesn't throw any errors.

Why don't you try that out, and see if it works correctly for you? Big Grin


Windell H. Oskay
drwho(at)evilmadscientist.com
http://www.evilmadscientist.com/

Forum Evil Scientist
Evil Scientist

Status: offline

Registered: 06/15/06
Posts: 1932
Sunnyvale, CA

Profile Email Website  
   
By: Anonymous: linxdev () on Friday, August 26 2011 @ 01:19 PM PDT  
Anonymous: linxdev


You're right. It is not needing those files so it does compile.

The IDE must be smart enough to see a main(). Onmy CLI environment using Makefiles I renamed main() to _loop().

PHP Formatted Code

void loop() { _loop(); }
void setup() {   }
 



Needs more tweaking but it should be good.





       
   
By: Windell (offline) on Friday, August 26 2011 @ 01:25 PM PDT  
Windell

>The IDE must be smart enough to see a main().

Apparently so. IIRC, the way that it works internally is that the IDE checks to see whether setup and loop are defined.


Windell H. Oskay
drwho(at)evilmadscientist.com
http://www.evilmadscientist.com/

Forum Evil Scientist
Evil Scientist

Status: offline

Registered: 06/15/06
Posts: 1932
Sunnyvale, CA

Profile Email Website  
   
By: Anonymous: linxdev () on Friday, August 26 2011 @ 03:08 PM PDT  
Anonymous: linxdev


I looked around on the web and all I could find was .wav files. This project generates a live clicking sound, which varies in rate, and also uses an LM386 to drive an 8 ohm speaker. I've bought a Diavolino for the final build, but the port from C is a bit beyond me at this point.



Try not to drive more than 20ma from the ping the LM386 is attached to. On a device I've built I use a 2N2222 as a switch to drive the speaker. I have a 1,5" speaker and this works well. You tie Vcc to a 100ohm resistor and that to E. Tie the pin driving the PWM to a 100ohm resistor and that to B. Tie C to ground. Use something like a polarised 47uf cap between E and the speaker with the negative going to the speaker. This works very well for me and I do not have to burn up a LM386. I have about 500 2N2222 transistors in my stock and hundreds of resistors.

Of course to drive this speaker I'm using Arduino's tone API.





       
   
By: Anonymous: Jeff Haas () on Friday, August 26 2011 @ 07:41 PM PDT  
Anonymous: Jeff Haas

Wow, I finally get time to get back to this and there's a ton of info. Thanks!

Before I asked for help, I had tried the code in the Arduino IDE. I'd commented out the two includes that it didn't know, but when I tried the Verify/Compile command, I got back these errors:

sketch_aug26b.cpp: In function 'void led_out(uint8_t)':
sketch_aug26b:52: error: 'B_DATA_PORT_MASK' was not declared in this scope
sketch_aug26b.cpp: In function 'void set_compare_timer1(uint16_t)':
sketch_aug26b:81: error: 'HIGHBYTE' was not declared in this scope
sketch_aug26b:82: error: 'LOWBYTE' was not declared in this scope
sketch_aug26b.cpp: In function 'void ioinit()':
sketch_aug26b:130: error: 'B_DATA_PORT_MASK' was not declared in this scope

On my system it won't upload. Question

When I saw those I took some time to research them and realized I needed to ask for help.

Regarding using one Arduino board as an ISP...I had looked at that, but all the info was about uploading a bootloader to a chip, not an entire program. Is there some assumption I'm missing here?

Jeff





       
   
By: Windell (offline) on Friday, August 26 2011 @ 10:00 PM PDT  
Windell

I've tried twice, on two different computers, and it compiles just fine.

It sounds like you are not testing the same code. If you get "''B_DATA_PORT_MASK' was not declared in this scope," that's just plain wrong-- you can see it there plain and simple.

Try again. Copy the code that you pasted here-- the whole thing --and paste it into a new *empty* Arduino window (without any setup() or loop()). Comment out the two lines with "iocompat2.h" and "pin_macros.h," and see if that compiles. And, don't try to upload if it doesn't compile.


Windell H. Oskay
drwho(at)evilmadscientist.com
http://www.evilmadscientist.com/

Forum Evil Scientist
Evil Scientist

Status: offline

Registered: 06/15/06
Posts: 1932
Sunnyvale, CA

Profile Email Website  
   
By: Anonymous: Jeff Haas () on Saturday, August 27 2011 @ 12:52 AM PDT  
Anonymous: Jeff Haas

D'oh! I'd made a typo in how I commented out the two lines.

I used /* for both, instead of:

/* blah
blah
*/

I knew that I'd copied the code properly and hadn't changed anything. Your comment about how it should be declared was my clue. Oops!





       
   
By: Anonymous: Jeff Haas () on Saturday, August 27 2011 @ 02:20 AM PDT  
Anonymous: Jeff Haas

OK, it's uploaded but I can't quite figure out which pins he's using for output.





       
   



 All times are PDT. The time is now 02:54 PM.
Normal Topic Normal Topic
Locked Topic Locked Topic
Sticky Topic Sticky Topic
New Post New Post
Sticky Topic W/ New Post Sticky Topic W/ New Post
Locked Topic W/ New Post Locked Topic W/ New Post
View Anonymous Posts 
Able to Post 
Filtered HTML Allowed 
Censored Content 

Evil Mad Scientist Forum Archives — Read only!

Please visit our new forums for new discussions.


DIY Hardware for Electronic Art


The Original Egg-Bot Kit


Octolively
Interactive LED kits


Meggy Jr RGB
LED matrix game
development kit.


Business-card sized
AVR target boards


Peggy 2
LED Pegboard kits

My Account






Lost your password?