Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Number crunching code wanted...!

Options
  • 21-07-2010 6:22pm
    #1
    Closed Accounts Posts: 7,134 ✭✭✭


    Hi lads,

    I am looking for some algorithms I can run on an 8 bit microcontroller, has anyone any links or ideas.?

    I saw this one

    http://acumensoftwareinc.com/TechNotes/NewtonRaphson/

    but think it may be over kill for my requirements, plus I couldn't get it to run on avr studio.


    has anyone any other recommendations.?

    cheers.


Comments

  • Registered Users Posts: 1,393 ✭✭✭Inspector Gadget


    You're writing code for an 8-bit AVR, based on what you're saying; either an ATTINY or ATMEGA or similar.

    First thing, if you're using the free gcc compiler, then it doesn't do C++ (that'd be g++, which doesn't exist for that platform as far as I know).

    Second, you'd need to think about memory size for your designs, assuming you want to run them on an actual micro. I know the devices you can choose from don't natively support multiplication or division (see the AVR200 technical note to see what I mean). Ditto for floating point numbers (!), or integers greater than 8 bits long. Where workarounds are available, they contribute significantly to the final code size, which is pretty critical if you need it to run on a given device.

    I really think that the platform isn't suitable for what you have in mind. Why do you want to do maths on an eight-bit micro?

    I'm not sure what else to suggest, apart from maybe going on to http://www.avrfreaks.net/ and seeing what's there?

    Hope this helps,
    Gadget


  • Registered Users Posts: 558 ✭✭✭wobbles-grogan


    What sort of maths are you looking to run? And more to the point, why? :-)

    Also, what Micro-controller are you using?
    It might be worth your while to write everything in assembly if your going for speed!


  • Closed Accounts Posts: 7,134 ✭✭✭x in the city


    hi guys

    I have this micro

    http://www.atmel.com/dyn/products/product_card.asp?PN=ATmega328P

    with 32k of flash memory

    I am using avr studio with the gcc plug in for comping and debug.

    and the reason for using number crunching, is to measure currrent activity whilst activity is going on.

    it will be marginal or minimal but it doesn't matter.

    actually, I could implement something like an ALU but I figured some algorithms would be easier to implement.


    any ideas lads?


  • Registered Users Posts: 1,393 ✭✭✭Inspector Gadget


    Well, at least you have the top-end device in that family, which is no bad thing.

    How and ever, it is still an 8-bit part with no ALU/FPU capability; now, to be fair, the vast majority of stuff performed in embedded systems is either integer-only or (where possible) simplified such that it can be run on an integer-based system. If you have to do something complex like floating point maths, you should be looking at a 16-bit system at the very least - an Arm, DSPic, PIC32, XMEGA or something like that.

    The smallest option for IEEE754 (the standard for representing floating point numbers in binary form) that I'm aware of is 16 bits long, so you're fighting an unnecessary uphill battle with an 8-bit micro.


  • Registered Users Posts: 558 ✭✭✭wobbles-grogan


    I'm not entirely sure what your asking for here.

    Do you know what you'll be calculating? Do you know what formula you need to use? Can you get inputs from the outside world(using sensors or input buttons or whatever)? What formula will you be using for calculating "activity"? What activity are you trying to measure?

    Sorry for all the questions, im just trying to understand what your at is all :-)

    If you know what formula you need to implement, how to get inputs etc then it should be easy program the chip to do what you need using the data sheet supplied with it (or on the website you gave)


  • Advertisement
  • Closed Accounts Posts: 7,134 ✭✭✭x in the city


    I'm not entirely sure what your asking for here.

    Do you know what you'll be calculating? Do you know what formula you need to use? Can you get inputs from the outside world(using sensors or input buttons or whatever)? What formula will you be using for calculating "activity"? What activity are you trying to measure?

    Sorry for all the questions, im just trying to understand what your at is all :-)

    If you know what formula you need to implement, how to get inputs etc then it should be easy program the chip to do what you need using the data sheet supplied with it (or on the website you gave)
    >>>>>>>>>>>


    hi lads and thanks for the feedback,

    ok, you are right, why am i doing this on a feeble micro.?

    well, I am doing a project on power consumption, I already have a programmable buck converter. (LP3907), I use hyperterminal to program my outputs to a load.

    which in my case is my atmel micro.

    what I wish to do is have the micro performing tasks, of course it would be useful to have a real processor or a FPGA or Hell, a Core 2 Duo doing some fancy routines, but that's just not possible...! :p:p

    when I have my basic but still useful 328p doing some tasks, I want to measure the change in current, I know this will be minimal but it doesn't matter.

    what I need to do is somehow try get some code programmed into it in the first place.. and I am a bit stumped.

    I am not at all concerned as to what I do or what results I get, I just need to get it doing some activity as such.

    does that make sense?

    I should point out, that i have got a 328p and its not negotiable, getting anything else...!


  • Registered Users Posts: 1,393 ✭✭✭Inspector Gadget


    Right. Well, off the top of my head, you certainly don't need high-brow mathematics to push the thing reasonably hard. Anything done all the time will keep it nice and busy.

    However, the chip you have is an extremely low-power device, and as such the miniscule variations in current will actually be pretty tough to measure (you're talking about 14 milliamps MAX here, worst cast scenario, while idle currents will be significantly less). A heftier CPU (or perhaps an older, less efficient one) that will actually generate meaningful heat (and therefore consume meaningful current) would be easier to work with here.

    Also, for what it's worth, the Atmega328 is the core of the current generation arduino, and can be programmed with Arduino scripts with a little extra work using ICSP (In-Circuit Serial Programming) and something like an AVRisp mk II? Bear in mind though that if you're doing this on a breadboard, you'll have to build/buy a little adaptor to convert the 2x3 pin connector on the programmer to suit being stuck into a breadboard. There's a whole load of pre-fabricated Arduino code there you could use to push the processor around a bit and see how much current it draws.

    One other thing - the DC-DC converter you're using seems to be important... are you trying to operate it using the Atmega, or what?


  • Closed Accounts Posts: 7,134 ✭✭✭x in the city


    Sir, you have my work down to a Tee......!

    I have an arduino as my source, that is runing hyperterminal... and thus drives my buck converter, the buck itself is providing the voltage to my load

    my 'other' 328p.

    I like to make things as confusing as possible it seem...:rolleyes:

    I can program the buck on the fly, from up to a max of 3.5volts.

    Once I get some math/algorithims, or basic stuff going on, I have to somehow regulate the voltage into the load device, according to its activity.

    aka, some power management.

    what do you think of the math part, I have this wrote out, would it even work...?!

    [HTML]#include <avr/io.h>

    #define F_CPU 16000000

    #include <util/delay.h>


    int main (void)

    {

    int i = 0;

    // set PORTD for output

    DDRD = 0xFF;

    while (i < 10) { // cycle through bits of port d

    for(i = 1; i < 128; i = i*2)

    {

    PORTD = i;
    _delay_loop_2(30000);

    }

    for(i = 128; i > 1; i -= i/2)

    {

    PORTD = i;
    _delay_loop_2(30000);

    }
    }

    return 0;

    }




    // blink the 7 led's for 2 seconds to signal start of math operation


    void blinky1 (void) {

    DDRD = 0b11111111;

    PORTD = 0b11111111;

    // wait 2 seconds

    _delay_ms(2000);

    // Turn off led's

    PORTD = 0b00000000;

    }

    // perform some math

    char z;
    char z1;
    char y;
    char y1;
    x = 12;
    x1 = 9;

    int index;

    void math (void){



    while ( x <= 256) {

    for (index = 0; index <256; index ++)


    x = x *2;

    }

    while (x >=0 )

    x = x/2 *1050 ;

    {

    }


    y = (char)x+3; // convert x to a char and add 3, place answer into y

    x = (int)y; // extend y to an int and assign it to x

    y1 = (char) x1/2; // convert x1 to a char, divide by 2 and place answer into y1

    z = (y1 * y)/12 + x/x1 * 2; // do some math!

    x = x+1/z;


    if (x >= 1) {



    // blink leds for 3 seconds



    DDRD = 0b11111111;

    PORTD = 0b11111111;

    // wait 2 seconds

    _delay_ms(3000);

    // Turn off led's

    PORTD = 0b00000000;


    }


    else {

    PORTD = 0b11110000;
    // wait 2 seconds, turn on upper bits of port d

    _delay_ms(3000);

    // Turn off led's

    PORTD = 0b00000000;


    }



    }


    [/HTML]


  • Registered Users Posts: 1,393 ✭✭✭Inspector Gadget


    I'm not entirely sure what you're trying to achieve here. For one thing, you seem to be re-using the variable 'i' a hell of a lot, within the same scope, which looks to me to be asking for trouble.

    Some of your loops are odd too. You're not thinking like someone who's dealing with a very limited platform; I can't say I'm an expert either, but for the sake of example, this:
           for(i = 1; i < 128; i = i*2)
           {
    
           PORTD = i;
           _delay_loop_2(30000);
    
           }
    

    Is probably better done this way (the "approved" way, as far as I can tell):
    for (i = 0; i < 7; i++)
    {
    	PORTD = (1 << i);
    	// Insert delay stuff here.
    }
    

    Assuming it's the one half of a "Knight Rider" style wave you want to set up in the output LEDs as I think it is. (The << operator is a left shift; it moves all the bits left one place, which is equivalent (excepting carry situations) to multiplying by two. 1 << 0 = 1; 1 << 1 = 2, 1 << 2 = 4, 1 << 3 = 8 ... you get the idea. For the other half of your "wave", just run the loop condition backwards. It also avoids the multiplication and division I was warning you about.

    Also, blinky1() and math() don't get called from main() yet, so they don't do anything yet. If the variables being defined outside the function declarations are meant to be something like globals, I think you'll need to declare them as volatile.

    In all seriousness, go on to avrfreaks.net, register, and look at the projects they have up there. Also hunt around for arduino code snippets. You'll learn a lot that way.

    Hope this helps,
    Gadget


  • Registered Users Posts: 1,228 ✭✭✭carveone


    If you don't mind me shoving my oar in here, I'd just like to say that it wasn't that long ago that doing floating point maths on a processor was a no no if you wanted any sort of performance.

    Noone had a 386DX or 486DX for example, they were too expensive. The SX variants were usual and they had no floating point unit. FP operations were emulated by whatever compiler you were using and were normally dog slow. If you were writing fast programs, you used fixed point and lookup tables. You didn't even use cmp when xor would do.

    I think this point has been lost a bit but microcontrollers and embedded systems bring it all back.

    There is _plenty_ of code out there to do maths. There are copious application notes for both the PIC microcontrollers and the AVRs. Here's a quick PIC reference (that in turn references Microchips app notes) and I know I saw an Apnote for the AVR that showed you fixed point math in 8.8 recently. Go googling...

    Note that the AVRs have a MUL instruction. The PIC16s didn't so you had to mulitply by repetative addition and shifts. Which was quite easy actually.


  • Advertisement
  • Closed Accounts Posts: 7,134 ✭✭✭x in the city


    carveone wrote: »
    If you don't mind me shoving my oar in here, I'd just like to say that it wasn't that long ago that doing floating point maths on a processor was a no no if you wanted any sort of performance.

    Noone had a 386DX or 486DX for example, they were too expensive. The SX variants were usual and they had no floating point unit. FP operations were emulated by whatever compiler you were using and were normally dog slow. If you were writing fast programs, you used fixed point and lookup tables. You didn't even use cmp when xor would do.

    I think this point has been lost a bit but microcontrollers and embedded systems bring it all back.

    There is _plenty_ of code out there to do maths. There are copious application notes for both the PIC microcontrollers and the AVRs. Here's a quick PIC reference (that in turn references Microchips app notes) and I know I saw an Apnote for the AVR that showed you fixed point math in 8.8 recently. Go googling...

    Note that the AVRs have a MUL instruction. The PIC16s didn't so you had to mulitply by repetative addition and shifts. Which was quite easy actually.


    thanks for that boss,

    can anyone tell me how i link up c code to the main(),

    as pointed out by inspector

    say I got

    main(){

    // do something

    }


    void(nowdothis){

    // do this next

    }


    how do i link up the two of these so they run in sequence??


  • Registered Users Posts: 1,393 ✭✭✭Inspector Gadget


    I think the biggest problem here is that the power consumption of the microcontroller will be so small that it'll be difficult to measure.

    Also, something to bear in mind - the total current that the chip can sink/source across ALL PINS is 20mA or so - if you're looking at driving more than two LEDs at once, say, you'll need to give it some outside help (either discrete transistors, or a driver chip like a ULN2803, or something like that).

    When it comes to how to orchestrate what does what when, the main() function (or more accurately its compiled equivalent) will be called automatically when the micro powers up; if you want stuff to happen, it goes in there (you call a function by naming it and passing in any parameters it requires) wherever you need it run. External functions (such as nowdothis() as you have it above) are a mechanism to package up chunks of code so that they can either be re-used (you declare a function once, and can call it as often as you like - it makes the overall program smaller than if you just copied and pasted the code in the function wherever you needed that behaviour). Alternatively, if you want divide up the code into logical chunks, then functions are the way to go. There are also special-purpose functions used by the AVR gcc compiler, such as interrupt service routines (ISRs), but I think that's a discussion for another day.

    Hope this helps...
    Gadget


  • Closed Accounts Posts: 7,134 ✭✭✭x in the city


    Hi ya


    well I have 8 leds hooked up and wrote a code that turns them on, once by one, the total current is ca 37mA.

    I need to do another code now that uses operands and see how that fares.

    can you tell me how I would simplify code for my leds, I have like
    /*
    
    cycle through all leds on PORTD one by one with a 1 second interval
    
    
    */
    
    
        {
    
        PORTD = 0b10000000;
        _delay_ms(1000); // wait one second
       
        PORTD = 0b11000000;
        _delay_ms(1000);
       
        PORTD = 0b11100000;
        _delay_ms(1000);
       
        PORTD = 0b11110000;
        _delay_ms(1000);
       
        PORTD = 0b11111000;
        _delay_ms(1000);
       
        PORTD = 0b11111100;
        _delay_ms(1000);
    
    
    /*
    
    repeat the procedure for PORTB
    
    
    
    */
    


    I want to reduce the number of lines and take out common elements and end up with something like
    void write_pattern_portb_delay(uint8_t pattern, int8_t ms) {
    }
    
    and call the function
    
    //
    	write_pattern_portb_delay(0b10000001, Delay_ms(1000))
             ................................... etc
    
    
    

    basically have a bit pattern followed by the delay, how do i go about creating a function for this?


  • Registered Users Posts: 1,393 ✭✭✭Inspector Gadget


    Erm, how much experience do you have in any form of programming? I'm trying to figure out which part of this you have difficulty with.


  • Closed Accounts Posts: 7,134 ✭✭✭x in the city


    hello,

    not a lot of coding..! , i missed out on all coding unfortunately, have done some verilog though.

    I got this much going and it does the trick. leds consume 107mA, and the math uses 24.6mA

    what do you think? im not actually interested in the leds at all, I am interested in some data activity, I noticed the maths used up slightly more current when i messed around the with code a bit, in the order of 200mA more.

    I suppose what i want to do is have some math code that returns a variable, and run the code again and again with gradually decreasing voltages, until such a time as the variable does not return at all, or just returns garbage.?
    Of course i want some code that does'nt just re-use values, i want it to use new values on new clock cycles to keep it churning out some data on clock cycles.


    I can also use a pre scaler to reduce my clock frequency, but i want to do some of the above first.

    does that make sense.?
    #include <avr/io.h>
    #define F_CPU 11000000 // 11Mhz Crystal used here
    #include <util/delay.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    #define Delay_ms(x)  _delay_ms(x)
    
    
    
    
    /*
      
    
      A routine to measure current consumption on a 328P
     
      Use PORTD 2-7 for LED1 - LED6
      Use PORDB 0-1 for LED7 - LED8
     
     The circuit:
    
    
     * LED's are all RED, with a 2K2 resistor to ground
     
     
    
    */
    
    
    void pattern();
    void reset_d();
    void maths();
    
    
    
    /*
    
    cycle through all leds on PORTD one by one with a 1 second interval
    
    
    */
    
    void pattern(){
    
    	
    
     	PORTD = 0b10000000;
        _delay_ms(1000); // wait one second
       
        PORTD = 0b11000000;
        _delay_ms(1000);
       
        PORTD = 0b11100000;
        _delay_ms(1000);
       
        PORTD = 0b11110000;
        _delay_ms(1000);
       
        PORTD = 0b11111000;
        _delay_ms(1000);
       
        PORTD = 0b11111100;
        _delay_ms(1000);
    
    
    /*
    
    repeat for PORTB
    
    
    */
    
    
    	PORTB = 0b00000001;
        _delay_ms(1000); // wait one second
       
       // PORTB = 0b00000011;
        //_delay_ms(1000);
    
    }
    
    void reset_d(){
    
    	PORTD = 0;
    	PORTB = 0;
    
    	}
    
    
    
    void maths(){
    
    	int a = 1;
    	int b = 2;
    	int c = 0;
    	int d,e;
    	int i;
    
    	for(i =0; i < 10 ; i++){
    	
    		a = b  * c;
    		d*= e; 
    
    		c = (a+b);
    		d = (a+c);
    		e = (a+d);
    		c = (a+b) * d;
    
    
    	_delay_ms(1000);
        PORTB = 0b00000010; // led on PB5
    
    		}
    
    
    }
    
    
    
    int main (void){
    
    	DDRD = 0xFF; 
    	DDRB = 0xFF;
    
    
    while(1){
    
    
    
    
    
    	PINB == 0b00000100 ? pattern() : maths(); // if PB2 is high do the led, otherwise do the math.
    
            _delay_ms(10000);
    		reset_d();
    
    
    }   
    
    
    
    }
    


  • Registered Users Posts: 1,393 ✭✭✭Inspector Gadget


    I'm far too dopey at this time of night to give you a detailed answer, but I assume you've seen the maximum ratings in the datasheet for the ATMEGA? If not, have a gander at pages 313-314 (I'm looking at doc8161.pdf) - especially the little box at the top of 313 and the notes at the top of page 314 about total current sink and source capabilities - in case you're pushing the thing a little hard.

    Other than that, you may want to turn off the brown-out detector (BOD) on the device if you plan to intentionally run it below spec when it comes to supply voltages as otherwise it'll keep resetting itself waiting for the voltage to come back up. And of course remember that "outputting a variable" on a microcontroller means setting the states of the pins somehow, whether lighting LEDs, communicating over I2C or some other serial protocol, or USB or whatever. It'd probably be clever to have some way of verifying that the thing is still doing exactly as you'd expect?

    I'll try to remember to post something more detailed tomorrow when I'm awake.


  • Closed Accounts Posts: 7,134 ✭✭✭x in the city


    I'm far too dopey at this time of night to give you a detailed answer, but I assume you've seen the maximum ratings in the datasheet for the ATMEGA? If not, have a gander at pages 313-314 (I'm looking at doc8161.pdf) - especially the little box at the top of 313 and the notes at the top of page 314 about total current sink and source capabilities - in case you're pushing the thing a little hard.

    Other than that, you may want to turn off the brown-out detector (BOD) on the device if you plan to intentionally run it below spec when it comes to supply voltages as otherwise it'll keep resetting itself waiting for the voltage to come back up. And of course remember that "outputting a variable" on a microcontroller means setting the states of the pins somehow, whether lighting LEDs, communicating over I2C or some other serial protocol, or USB or whatever. It'd probably be clever to have some way of verifying that the thing is still doing exactly as you'd expect?

    I'll try to remember to post something more detailed tomorrow when I'm awake.


    I need to look into the brown out detector and disable it alright, I have a led running after it completes the math code in my listing, and it lights up. so i assume it does the crunching.

    I think i need to send all this across the usart and see figures in hyperterminal, real answers. lighting a led is not really ideal. the only thing is i need a max 232 now on my breadboard.

    what do you think?


Advertisement