example_code
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
example_code [2014/03/07 00:41] – created 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 ; | ||
+ | } | ||
+ | |||
+ | </ |