Sida 1 av 2
Pekare i en array, Arduino C
Postat: 2 december 2010, 20:58:12
av Bosen
På
denna sidan så hittade jag ett exempel på det jag vill göra. Exempelkod:
Kod: Markera allt
const char* cmd_array[] = {"help",
"delay",
"step",
"dir",
"start",
"stop",
0};
typedef void(*cmd_func_ptr)(char*);
cmd_func_ptr cmd_array_func_ptr[] = {&display_help,
&set_delay,
&set_step_mode,
&set_dir,
&do_start,
&do_stop,
0};
void parse_command(char* cmd)
{
byte i = 0;
do
if (strncmp(cmd_array[i], cmd, strlen(cmd_array[i])) == 0)
return (*cmd_array_func_ptr[i])(cmd);
while(cmd_array[i++]);
Serial.print("unkown command: ");
Serial.println(cmd);
}
void do_start(char* cmd)
{
unsigned long temp;
if (!motor_started)
{
if (sscanf(cmd,"%*s %lu", &temp) == 1)
{
step_to_do = temp;
motor_started = 2;
digitalWrite(ENABLE_pin, LOW);
Serial.print("Start motor to do ");
Serial.print(step_to_do);
Serial.println(" steps");
}
else
{
motor_started = 1;
digitalWrite(ENABLE_pin, LOW);
Serial.println("Start motor");
}
}
else
{
Serial.println("Motor is already started");
}
}
Killen läser alltså av ett kommando från serieporten och skickar sedan via "en pekare i en array" vidare i programmet. Jag fick inte killens exempelkod (hela koden finns på sidan) att fungera, men tanken som han har är intressant. Problemet är att jag inte riktigt förstår detta med pekare (pointers) och lyckas inte hoppa till olika funktioner som denna killen visar. Finns det någon som har fått detta att fungara och kan visa mig ett bättre exempel?
om vi säger att jag har en array som heter ARRAY1 med 4 st olika funktioner:
så vill jag ungefär göra såhär:
och ska då hoppa till funktionen FUNC2
hoppas ni förstår vad jag frågar om

Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:17:56
av snigelen
I programmet ovan är det ju en array med funktionspekare. Funktionen med index i anropas där så här
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:23:15
av sodjan
Är det inte exakt så Bosen har gjort !?
Du får kanske förtydliga ditt inlägg lite...
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:25:10
av snigelen
Han har inte gjort någonting annat än att försöka förstå vad någon annan gjort.
Du kanske skulle läsa igenom innan du svarar...
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:30:10
av sodjan
Ja, OK, du menar att det (enkla) förslag som Bosen visar sist inte fungerar.
Jo, det är ju sant...
Det var inte helt tydligt i förstainlägget om den kod som visas är någon annans kod
("exempelkoden") eller om det är den kod som Bosen inte får att fungera. Bäst vore med
ett komplett exemepl från Bosen som faktiskt är den kod som han försöker få att fungera.
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:32:22
av snigelen
Ja

Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:35:55
av Bosen
nja... jag har provat hans kod... men får den inte att funka.... jag undrar hur man kan få det att funka!
som sagt så finns ju denna arrayen:
Kod: Markera allt
typedef void(*cmd_func_ptr)(char*);
cmd_func_ptr cmd_array_func_ptr[] = {&display_help,
&set_delay,
&set_step_mode,
&set_dir,
&do_start,
&do_stop,
0};
..men hur kan man skriva
jag fattar inte vad första cmd_func_ptr betyder.....
jag behöver helt enkelt en bättre förklaring.....
hela koden som jag inte får att fungera:
Kod: Markera allt
/******************************************************************
* Arduino Command Line Interface - Stepper motor rev 0.1
* Quentin Berthet // modprobe.ch
* tumnao@gmail.com
* 3.10.2010
*****************************************************************/
/* Pin definition ************************************************/
int SR_pin = 6;
int MS1_pin = 4;
int MS2_pin = 7;
int ENABLE_pin = 5;
int DIR_pin = 3;
int STEP_pin = 2;
/* Commands arrays ***********************************************/
const char* cmd_array[] = {"help",
"delay",
"step",
"dir",
"start",
"stop",
0};
typedef void(*cmd_func_ptr)(char*);
cmd_func_ptr cmd_array_func_ptr[] = {&display_help,
&set_delay,
&set_step_mode,
&set_dir,
&do_start,
&do_stop,
0};
/* Globals *******************************************************/
unsigned long delay_between_step = 100000; //0.1 s
byte step_mode = 1;
byte dir = 0;
byte motor_started = 0;
unsigned long step_to_do = 0;
/* Motor control *************************************************/
void do_step(void)
{
delayMicroseconds(2); //datasheet specify 1us min
digitalWrite(STEP_pin, HIGH);
delayMicroseconds(2); //datasheet specify 1us min
digitalWrite(STEP_pin, LOW);
if (motor_started == 2)
if (--step_to_do == 0)
{
motor_started = 0;
digitalWrite(ENABLE_pin, HIGH);
}
}
void check_deadline()
{
static unsigned long next_dead_line = 0;
/* TODO : add micros() overflow check */
if (next_dead_line <= micros())
{
do_step();
next_dead_line = micros() + delay_between_step;
}
}
void change_step_mode(int s)
{
switch(s)
{
case 1:
digitalWrite(MS1_pin, LOW);
digitalWrite(MS2_pin, LOW);
break;
case 2:
digitalWrite(MS1_pin, HIGH);
digitalWrite(MS2_pin, LOW);
break;
case 4:
digitalWrite(MS1_pin, LOW);
digitalWrite(MS2_pin, HIGH);
break;
case 8:
digitalWrite(MS1_pin, HIGH);
digitalWrite(MS2_pin, HIGH);
break;
default:
break;
}
}
/* Command line Functions ****************************************/
void display_help(char* cmd)
{
int i=0;
Serial.println("Command list:");
while (cmd_array[i])
{
Serial.print(" ");
Serial.println(cmd_array[i++]);
}
}
void do_start(char* cmd)
{
unsigned long temp;
if (!motor_started)
{
/* TODO : add if delay is below a limit,
* use an acceleration curve */
if (sscanf(cmd,"%*s %lu", &temp) == 1)
{
step_to_do = temp;
motor_started = 2;
digitalWrite(ENABLE_pin, LOW);
Serial.print("Start motor to do ");
Serial.print(step_to_do);
Serial.println(" steps");
}
else
{
motor_started = 1;
digitalWrite(ENABLE_pin, LOW);
Serial.println("Start motor");
}
}
else
{
Serial.println("Motor is already started");
}
}
void do_stop(char* cmd)
{
if (motor_started)
{
motor_started = 0;
digitalWrite(ENABLE_pin, HIGH);
if (step_to_do > 0)
{
Serial.print("Motor stopped, but ");
Serial.print(step_to_do);
Serial.println(" steps to do remaining...");
}
else
Serial.println("Motor stopped");
step_to_do = 0;
}
else
{
Serial.println("Error: motor already stopped");
}
}
void set_delay(char* cmd)
{
unsigned long temp;
if (sscanf(cmd,"%*s %lu", &temp) == 1)
delay_between_step = temp;
Serial.print("delay between step : ");
Serial.print(delay_between_step);
Serial.println(" us");
}
void set_step_mode(char* cmd)
{
int temp;
if (sscanf(cmd,"%*s %d", &temp) == 1)
{
if ((temp == 1) ||
(temp == 2) ||
(temp == 4) ||
(temp == 8))
{
step_mode = temp;
change_step_mode(step_mode);
}
else
Serial.println("Error: step-mode must be 1,2,4,8");
}
switch (step_mode)
{
case 1:
Serial.println("Full-step");
break;
case 2:
Serial.println("Half-step");
break;
case 4:
Serial.println("Quarter-step");
break;
case 8:
Serial.println("Eighth-step");
break;
}
}
void set_dir(char* cmd)
{
int temp;
if (sscanf(cmd,"%*s %d", &temp) == 1)
{
if (temp == 0)
dir = 0;
else
dir = 1;
digitalWrite(DIR_pin, dir);
}
Serial.print("direction : ");
Serial.println(dir, DEC);
}
/* Command line parsing ******************************************/
void parse_command(char* cmd)
{
byte i = 0;
do
if (strncmp(cmd_array[i], cmd, strlen(cmd_array[i])) == 0)
return (*cmd_array_func_ptr[i])(cmd);
while(cmd_array[i++]);
Serial.print("unkown command: ");
Serial.println(cmd);
}
void push_byte_to_cmd(char b)
{
static char cmd_buf[32];
static char cmd_ptr = 0;
if (b == '\n')
{
cmd_buf[cmd_ptr] = 0; //assure that there is a null byte
Serial.println();
parse_command(cmd_buf);
Serial.print(">");
//clear command
cmd_ptr = 0;
memset(cmd_buf, 0, sizeof(cmd_buf));
}
else if(isprint(b))
{
Serial.print(b);
cmd_buf[cmd_ptr++] = b;
if (cmd_ptr >= sizeof(cmd_buf)-1) //1 for null byte
{
Serial.println();
Serial.println("Command too long");
cmd_ptr = 0;
memset(cmd_buf, 0, sizeof(cmd_buf));
}
}
}
/* Main **********************************************************/
void setup(void)
{
pinMode(SR_pin, OUTPUT);
pinMode(MS1_pin, OUTPUT);
pinMode(MS2_pin, OUTPUT);
pinMode(ENABLE_pin, OUTPUT);
pinMode(DIR_pin, OUTPUT);
pinMode(STEP_pin, OUTPUT);
//A3977 config
digitalWrite(ENABLE_pin, HIGH); // disable input
digitalWrite(SR_pin, LOW); // low: active mode off
step_mode = 1;
change_step_mode(step_mode); // start with full steps
dir = 0;
digitalWrite(DIR_pin, dir);
digitalWrite(STEP_pin, LOW);
Serial.begin(115200);
Serial.println("arduino CLI v0.1");
Serial.print(">");
}
void loop(void)
{
if (motor_started > 0) check_deadline();
if (Serial.available() > 0) push_byte_to_cmd(Serial.read());
}
/* EOF ***********************************************************/
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:43:48
av sodjan
"Inte fungerar" är en för dålig beskrivning av problemet.
Vad fungerar inte ? Vad fungerar ?
Det finns ju massor av "print", fungerar något av det ?
Finns det någor debugger/simulator där du kan "stega" / "köra" koden ?
Har du testat att göra ett litet test-case för att enbart testa
funktionsanrop via pekare ? Om inte, gör det !
Har du gjort någon felsökning alls (och i så fall, vilken?) ?
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:44:38
av AndLi
typedef void(*cmd_func_ptr)(char*);
cmd_func_ptr är alltså en pekare till en funktion som tar en char* som argument och inte returnerar något.
cmd_func_ptr är alltså datatypen, som råkar vara en funktionspekare i detta fall..
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:45:13
av snigelen
> jag fattar inte vad första cmd_func_ptr betyder.....
cmd_func_ptr är definierad som
vilket är en definition av en pekare till en funktion som tar en char* som argument. Så
defineierar en array med pekare till sådana funktioner. (well inte pekare till pekare)
Men vad är det som inte fungerar? Hur fungerar det inte?
(sodjan hann före med relevanta frågor, och AndLi med relevant information)
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 21:55:41
av Bosen
är det altså typedef som skickar vidare? varför ett &-tecken i arrayen?
jag har testat koden genom att plocka bort allt som har med stegmotorn att göra och skrivit till serieporten i varje fuktion istället, men den verkar inte hoppa till funktionerna. Tyvärr finn det ingen debugger/simulator

Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 22:10:00
av Bosen
om jag lägger till följande i mitt eget program:
'
Kod: Markera allt
typedef void(*cmd_func_ptr)(char*);
cmd_func_ptr cmd_array_func_ptr[] = {&display_help,
&set_delay,
&set_step_mode,
&set_dir,
&do_start,
&do_stop,
0};
så får jag följande felmeddelande:
Kod: Markera allt
invalid conversion from 'void (*)()' to 'void (*)(char*)
varför?
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 22:41:16
av snigelen
> är det altså typedef som skickar vidare? varför ett &-tecken i arrayen?
Jag vet inte vad du menar med "skickar vidare". Men arrayen innehåller pekare (dvs adresser) till funktioner. &-tecknet ger just adressen till det som står efter.
> om jag lägger till följande i mitt eget program:
Exakt vad har du lagt till?
> så får jag följande felmeddelande:
Finns alla funktioner som du refererar till i arrayen? Är de av typ void func(char *)?
Här är ett litet exempel med funktionspekare (du får ta bort alla USB, jag hade ingen arduino till hands, bara en Maple; en stm32-grunka som går att programmera i Arduino-miljö)
Kod: Markera allt
void setup() {}
void func1(char *s)
{
SerialUSB.print("func1: ");
SerialUSB.println(s);
}
void func2(char *s)
{
SerialUSB.print("func2: ");
SerialUSB.println(s);
}
typedef void (*func)(char *);
func array[] = {&func1, &func2};
void loop() {
if (SerialUSB.available()) {
if (SerialUSB.read() & 1)
(*array[0])("I'm odd");
else
(*array[1])("I'm even");
}
}
Re: Pekare i en array, Arduino C
Postat: 2 december 2010, 23:03:49
av Bosen
TACK! äntligen ett exempel som funkar!!!!
nu ska jag kika närmare på detta och försöka förstå varför det fungerar!
För er som vill ha koden omgjord till arduino-kod:
Kod: Markera allt
void setup() {
Serial.begin(9600);
}
void func1(char *s)
{
Serial.print("func1: ");
Serial.println(s);
}
void func2(char *s)
{
Serial.print("func2: ");
Serial.println(s);
}
typedef void (*func)(char *);
func array[] = {&func1, &func2};
void loop() {
if (Serial.available()) {
if (Serial.read() & 1)
(*array[0])("I'm odd");
else
(*array[1])("I'm even");
}
}
Re: Pekare i en array, Arduino C
Postat: 3 december 2010, 09:32:04
av Icecap
Det är mycket fel att omdefiniera "void" till något alls!
Det hade varit intelligent att ge dessa funktioner ett eget namn till typen!
Exempel:
typedef T_FUNC (*func)(char *);
varefter dessa funktioner ska vara:
T_FUNC func1(char *s)
{
Serial.print("func1: ");
Serial.println(s);
}
Resten ska vara sig likt.
Orsaken: "void" används till så många andra funktioner och betyder "ingenting" så att omdeklarera det ord till annat kommer att ge fel i mängder.