Buy an Axon, Axon II, or Axon Mote and build a great robot, while helping to support SoR.
0 Members and 1 Guest are viewing this topic.
#define u8 unsigned char#define u16 unsigned int/////////////////////////////////////////////////////////////////////////////// set up job scheduler //// //// assumes a timer has to configured to interrupt every 1 ms ///////////////////////////////////////////////////////////////////////////////#define MAX_JOBS 16 // valid range is 1 to 254 volatile struct { // linked list of scheduled jobs in the form of a static array u8 id; u8 next; u16 time;} jobs[MAX_JOBS];volatile u8 nextjob; // next job to be run (chronologically) volatile u8 lastjob; // last job to be run (chronologically)volatile u16 jobtimer; // increments on each timer interrupt, auto-wraps to 0 void initjobs(void); // run once before scheduling any jobs void runjobs(void); // runs over and over in main loop void runjob(u8 id); // called by runjobs based on bits set in 'runnable' */void schedule(u8 id, u16 time); // schedule a job to run 'time' ms from now // specific job functions - can have up to 255 of them. unfortunately, they// don't currently accept any arguments. should be easy to add.void toggle_led1(void); #define TOGGLE_LED1 1void toggle_led2(void); #define TOGGLE_LED2 2 void toggle_led3(void); #define TOGGLE_LED3 3 ///////////////////////////////////////////////////////////////////////////////// Codevision-specific code for the AVR's "timer0 compare A match" interrupt// set up your MCU similarly to interrupt every 1 ms and simply increment jobtimer on interruptinterrupt [TIM0_COMPA] void timer0_compa_isr(void) { jobtimer++; }// an example main function that flashes LED1 for 250ms every second and// LED2 for 500ms every 2 seconds and LED3 for 100ms every half secondvoid main(void) { initjobs(); // MCU pin configuration omitted for brevity // schedule the first "blink" of each LED. // they'll then reschedule themselves as needed. schedule(TOGGLE_LED1, 100); schedule(TOGGLE_LED1, 350); schedule(TOGGLE_LED2, 100); schedule(TOGGLE_LED2, 600); schedule(TOGGLE_LED3, 100); schedule(TOGGLE_LED3, 200); while (1) { runjobs(); } } void toggle_led1(void) { PORTA.1 = ~PORTA.1; // codevision-specific for my MCU and schematic // main function scheduled the initial led-on and led-off, resulting in a blink. // we reschedule ourselves every second to blink every second schedule(TOGGLE_LED1, 1000); } void toggle_led2(void) { PORTA.2 = ~PORTA.2; schedule(TOGGLE_LED2, 2000);}void toggle_led3(void) { PORTA.3 = ~PORTA.3; schedule(TOGGLE_LED3, 500);} // initialize the job schedulervoid initjobs(void) { u8 i; for(i = 0; i < MAX_JOBS; i++) { jobs[i].id=0; jobs[i].time=0; jobs[i].next=i; } nextjob = 0; lastjob=0; }// run every job due to run right nowvoid runjobs() { u8 newnext; while(jobs[nextjob].id && jobs[nextjob].time == jobtimer) { runjob(jobs[nextjob].id); newnext = jobs[nextjob].next; jobs[nextjob].id = 0; jobs[nextjob].time = 0; jobs[nextjob].next = nextjob; nextjob = newnext; }}// run a specific job -- called by runjobsvoid runjob(u8 id) { switch(id) { case TOGGLE_LED1: toggle_led1(); break; case TOGGLE_LED2: toggle_led2(); break; case TOGGLE_LED3: toggle_led3(); break; }} // schedule a job to be run 'time' ms from nowvoid schedule(u8 id, u16 time) { u8 i; u8 freejob = 255; u8 prev = 255; /* find a free job slot. start with nextjob and work backwards, since empty slots are most likely to be found there. This also automatically handles the special case of an empty job list */ i = nextjob; for(i = nextjob; i != (u8)(nextjob + 1) % MAX_JOBS; i = (u8)(i - 1) % MAX_JOBS) { if(! jobs[i].id) { freejob = i; break; } } if(freejob >= MAX_JOBS) /* job list full. new job is lost. */ return; /* figure out where in the job list it will fit */ /* start with lastjob, since new jobs will generally be the last job */ if(jobs[lastjob].id && jobs[lastjob].time <= time + jobtimer) prev = lastjob; else { /* ok, then search from the beginning */ for(i = nextjob; jobs[i].id; i = jobs[i].next) { // ugly expression figures out if new job happens before or after jobs[i] if((jobs[i].time - jobtimer + 65536 * (jobtimer > jobs[i].time)) <= time) prev = i; else break; if(jobs[i].next == i) break; } } /* fill in freejob slot with new job info */ jobs[freejob].id = id; jobs[freejob].time = jobtimer + time; jobs[freejob].next = freejob; /* update next pointers */ if(prev < 255) { /* new job is not the next job */ if(jobs[prev].next != prev) jobs[freejob].next = jobs[prev].next; else lastjob = freejob; /* new job is the last job */ jobs[prev].next = freejob; } else { /* new job is the next job */ if(jobs[nextjob].id) jobs[freejob].next = nextjob; else lastjob = freejob; /* new job is the only job */ nextjob = freejob; }}
but i dont quite understand why there is a list of actions . . . is it just doing one action at a time until time T, then doing the next one? or can it handle all simultaneously? that would be very useful if say i had like 20 servos . . .also, what does 'volatile' mean?
im a mechanical engineer, software is my weakspot
Isn't this just a scheduler, then?