example_code
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revision | |||
| example_code [2014/03/07 00:51] – cedric.eloy | example_code [2018/05/22 10:33] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Example code ====== | ||
| + | |||
| + | ===== CAN communication with control boards ===== | ||
| + | |||
| + | The applications running in the embedded Linux environment can communicate with the IO boards through the CAN bus protocol. The high level protocol is a reduced version of the CANopen stack. | ||
| + | |||
| + | Here is how to write a Object Dictionary entry: | ||
| + | |||
| + | <code c od_write_master.c> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | /** | ||
| + | * \brief Initializes a raw socket for CAN communication | ||
| + | * \param ifname the interface, typically can0 | ||
| + | */ | ||
| + | int init_can(const char * ifname) | ||
| + | { | ||
| + | int s; | ||
| + | struct sockaddr_can addr; | ||
| + | struct ifreq ifr; | ||
| + | |||
| + | if((s = socket(PF_CAN, | ||
| + | perror(" | ||
| + | return -1; | ||
| + | } | ||
| + | |||
| + | strcpy(ifr.ifr_name, | ||
| + | ioctl(s, SIOCGIFINDEX, | ||
| + | |||
| + | addr.can_family | ||
| + | addr.can_ifindex = ifr.ifr_ifindex; | ||
| + | |||
| + | printf(" | ||
| + | |||
| + | if(bind(s, (struct sockaddr *)& | ||
| + | perror(" | ||
| + | return -2; | ||
| + | } | ||
| + | | ||
| + | return s; | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * \brief Writes OD entry | ||
| + | * \param s socket where to write to | ||
| + | * \param idx OD index | ||
| + | * \param subidx OD subindex | ||
| + | * \param val value to write | ||
| + | */ | ||
| + | int od_write(int s, uint16_t idx, uint8_t subidx, int32_t val) | ||
| + | { | ||
| + | struct can_frame frame; | ||
| + | | ||
| + | frame.can_id | ||
| + | frame.can_dlc = 8; | ||
| + | frame.data[0] = 0x23; | ||
| + | frame.data[1] = idx& | ||
| + | frame.data[2] = ( idx >> 8 ) & 0xFF ; | ||
| + | frame.data[3] = subidx ; | ||
| + | frame.data[4] | ||
| + | frame.data[5] | ||
| + | frame.data[6] | ||
| + | frame.data[7] | ||
| + | | ||
| + | write(s, &frame, sizeof(struct can_frame)); | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | ===== A simple UObject to control a motor ===== | ||
| + | |||
| + | <code c++ UQuimMotor.hpp> | ||
| + | #ifndef UQUIMMOTOR_HPP__ | ||
| + | #define UQUIMMOTOR_HPP__ | ||
| + | |||
| + | // Include the UObject declarations. | ||
| + | # include < | ||
| + | |||
| + | class UQuimMotor | ||
| + | : public urbi:: | ||
| + | { | ||
| + | public: | ||
| + | /** | ||
| + | * \brief C++ contructor. | ||
| + | | ||
| + | * \param name name given to the instance | ||
| + | | ||
| + | UQuimMotor(const std:: | ||
| + | |||
| + | /** | ||
| + | * \brief Urbi constructor | ||
| + | | ||
| + | * \param motor_id | ||
| + | * \return 0 on success | ||
| + | | ||
| + | int init(int motor_id); | ||
| + | | ||
| + | /** | ||
| + | * \brief Function notified when the speed is changed. | ||
| + | * \param v the UVar being modified | ||
| + | * \return 0 on success | ||
| + | | ||
| + | int speed_set(urbi:: | ||
| + | |||
| + | private: | ||
| + | urbi::UVar speed; | ||
| + | int motorId_m ; | ||
| + | int canSocket_m; | ||
| + | }; | ||
| + | # | ||
| + | |||
| + | </ | ||
| + | |||
| + | <code c++ UQuimMotor.cpp> | ||
| + | #include " | ||
| + | #include " | ||
| + | #include < | ||
| + | |||
| + | // Register the UMachine UObject in the Urbi world. | ||
| + | UStart(UQuimMotor); | ||
| + | |||
| + | // Bouncing the name to the UObject constructor is mandatory. | ||
| + | UQuimMotor:: | ||
| + | : urbi:: | ||
| + | { | ||
| + | // Register the Urbi constructor. | ||
| + | // part of the C++ constructor. | ||
| + | UBindFunction(UQuimMotor, | ||
| + | } | ||
| + | |||
| + | int UQuimMotor:: | ||
| + | { | ||
| + | if (! (motor_id == 1 || motor_id == 2) ) | ||
| + | { | ||
| + | printf(" | ||
| + | return 1; | ||
| + | } | ||
| + | motorId_m = motor_id ; | ||
| + | | ||
| + | canSocket_m = init_can(" | ||
| + | if (canSocket_m < 0) | ||
| + | { | ||
| + | printf(" | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | // Bind the UVars before using them. | ||
| + | UBindVar(UQuimMotor, | ||
| + | |||
| + | // Request that speed_set be invoked each time speed is changed. | ||
| + | UNotifyChange(speed, | ||
| + | |||
| + | // Success. | ||
| + | return 0; | ||
| + | } | ||
| + | |||
| + | int UQuimMotor:: | ||
| + | { | ||
| + | // Speed entry in QuimMotor entry is at index 0x60FF | ||
| + | // subidx indicates which motor to set | ||
| + | od_write(canSocket_m, | ||
| + | return 0 ; | ||
| + | } | ||
| + | |||
| + | </ | ||
