{"action":"created","issue":{"url":"https://api.github.com/repos/machinekit/machinekit/issues/589","labels_url":"https://api.github.com/repos/machinekit/machinekit/issues/589/labels{/name}","comments_url":"https://api.github.com/repos/machinekit/machinekit/issues/589/comments","events_url":"https://api.github.com/repos/machinekit/machinekit/issues/589/events","html_url":"https://github.com/machinekit/machinekit/issues/589","id":70954643,"number":589,"title":"HAL driver for CAN","user":{"login":"luminize","id":2206842,"avatar_url":"https://avatars.githubusercontent.com/u/2206842?v=3","gravatar_id":"","url":"https://api.github.com/users/luminize","html_url":"https://github.com/luminize","followers_url":"https://api.github.com/users/luminize/followers","following_url":"https://api.github.com/users/luminize/following{/other_user}","gists_url":"https://api.github.com/users/luminize/gists{/gist_id}","starred_url":"https://api.github.com/users/luminize/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/luminize/subscriptions","organizations_url":"https://api.github.com/users/luminize/orgs","repos_url":"https://api.github.com/users/luminize/repos","events_url":"https://api.github.com/users/luminize/events{/privacy}","received_events_url":"https://api.github.com/users/luminize/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/machinekit/machinekit/labels/enhancement","name":"enhancement","color":"84b6eb"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":145,"created_at":"2015-04-25T19:12:09Z","updated_at":"2015-10-20T09:28:08Z","closed_at":null,"body":"As a subissue of https://github.com/machinekit/machinekit/issues/586 I'll try to get history, questions, contemplations, answers, tips and all what passes collected into this issue.\r\n\r\nDuring the process I want to write down \"the stuff\" so when we release it into the wild we have the docs also ready to go. I'll do that in a dedicated branch can-in-machinekit here: https://github.com/luminize/machinekit-docs/tree/can-in-machinekit"},"comment":{"url":"https://api.github.com/repos/machinekit/machinekit/issues/comments/149492404","html_url":"https://github.com/machinekit/machinekit/issues/589#issuecomment-149492404","issue_url":"https://api.github.com/repos/machinekit/machinekit/issues/589","id":149492404,"user":{"login":"hekav","id":12659936,"avatar_url":"https://avatars.githubusercontent.com/u/12659936?v=3","gravatar_id":"","url":"https://api.github.com/users/hekav","html_url":"https://github.com/hekav","followers_url":"https://api.github.com/users/hekav/followers","following_url":"https://api.github.com/users/hekav/following{/other_user}","gists_url":"https://api.github.com/users/hekav/gists{/gist_id}","starred_url":"https://api.github.com/users/hekav/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hekav/subscriptions","organizations_url":"https://api.github.com/users/hekav/orgs","repos_url":"https://api.github.com/users/hekav/repos","events_url":"https://api.github.com/users/hekav/events{/privacy}","received_events_url":"https://api.github.com/users/hekav/received_events","type":"User","site_admin":false},"created_at":"2015-10-20T09:28:08Z","updated_at":"2015-10-20T09:28:08Z","body":"Hi Michael,\r\n\r\nThanks for the info. I did not know that the  RT-PREEMPT kernel performs so good. I will try this path.\r\n\r\nI have a peak-can pci card with 2 ports an a Festo Can controller CMMP-AS-C5-3A and a Festo EMMS-A5 motor.\r\n\r\nMy architecture off the driver looks like this:\r\n\r\nI did reuse the configuration part of the linuxcnc-ethercat-master (lcec-main.c it is a userspace component in hal) for the configuration. Only miner changes.  \r\nThe xml-file looks like this (it is the boot sequence for one controller) :\r\n\r\n\r\n<masters>\r\n  <master idx=\"0\" appTimePeriod=\"8000000\" refClockSyncCycles=\"1000\" nodeid=\"1\">\r\n    <slave idx=\"0\" type=\"CMMPASIP\" name=\"3A1\" nodeid=\"2\">\r\n    \r\n    \t    <!-- buffer_clear für interpolated positioning mode-->\r\n       <sdoConfig idx=\"60c4\" subIdx=\"06\"> <sdoDataRaw data=\"01\"/> </sdoConfig>\r\n     \r\n    \t   <!-- disable Slave's TPDO 1  mit nodid -->\r\n       <sdoConfig idx=\"1800\" subIdx=\"01\"> <sdoDataRaw data=\"82 01 00 c0\"/> </sdoConfig>\r\n    \r\n   \t\t   <!-- setup Slave's TPDO 1 TxPDO1 Anzahl der PDO Objecte = 0 -->\r\n       <sdoConfig idx=\"1A00\" subIdx=\"00\"> <sdoDataRaw data=\"00\"/> </sdoConfig>\r\n    \r\n    \t\t<!-- setup Slave's mapping TxPDO1 Mode of operation Display  subindex 2  subindex 1 ist default = Statusword-->\r\n       <sdoConfig idx=\"1A00\" subIdx=\"02\"> <sdoDataRaw data=\"08 00 61 60\"/> </sdoConfig>\r\n    \r\n    \t   <!-- setup Slave's mapping TxPDO1 Actual Position  subindex 3 -->\r\n       <sdoConfig idx=\"1A00\" subIdx=\"03\"> <sdoDataRaw data=\"20 00 64 60\"/> </sdoConfig>\r\n    \r\n      \t\t<!-- setup Slave's Anzahl der TxPDO Objecte = 3 -->\r\n       <sdoConfig idx=\"1A00\" subIdx=\"00\"> <sdoDataRaw data=\"03\"/> </sdoConfig>\r\n    \r\n      \t\t<!-- setup Slave's TxPDO1 TransmissionType auf Synctype = 0x01 -->\r\n       <sdoConfig idx=\"1800\" subIdx=\"02\"> <sdoDataRaw data=\"01\"/> </sdoConfig>\r\n       \r\n       \t   <!-- disable Slave's RPDO 1  mit nodid -->\r\n       <sdoConfig idx=\"1400\" subIdx=\"01\"> <sdoDataRaw data=\"02 02 00 c0\"/> </sdoConfig>\r\n       \r\n       \t   <!-- setup Slave's RPDO 1 RxPDO1 Anzahl der PDO Objecte = 0 -->\r\n       <sdoConfig idx=\"1600\" subIdx=\"00\"> <sdoDataRaw data=\"00\"/> </sdoConfig>\r\n       \r\n           \t\t<!-- setup Slave's mapping RxPDO1 Mode of operation  subindex 2  subindex 1 ist default = Controlword-->\r\n       <sdoConfig idx=\"1600\" subIdx=\"02\"> <sdoDataRaw data=\"08 00 60 60\"/> </sdoConfig>\r\n       \r\n          \t   <!-- setup Slave's mapping RxPDO1 Iterpolated Datarecord (sollposition)   subindex 3 -->\r\n       <sdoConfig idx=\"1600\" subIdx=\"03\"> <sdoDataRaw data=\"20 01 c1 60\"/> </sdoConfig>\r\n       \r\n       \r\n       \t\t<!-- setup Slave's Anzahl der RxPDO Objecte = 3 -->\r\n       <sdoConfig idx=\"1600\" subIdx=\"00\"> <sdoDataRaw data=\"03\"/> </sdoConfig>\r\n       \r\n         \t\t<!-- setup Slave's RxPDO1 TransmissionType auf Synctype = 0x01 -->\r\n       <sdoConfig idx=\"1400\" subIdx=\"02\"> <sdoDataRaw data=\"01\"/> </sdoConfig>\r\n       \r\n       \t   <!-- enable Slave's TPDO 1  mit nodid -->\r\n       <sdoConfig idx=\"1800\" subIdx=\"01\"> <sdoDataRaw data=\"82 01 00 40\"/> </sdoConfig>\r\n       \r\n        \t   <!-- enable Slave's RPDO 1  mit nodid -->\r\n       <sdoConfig idx=\"1400\" subIdx=\"01\"> <sdoDataRaw data=\"02 02 00 40\"/> </sdoConfig>\r\n    \r\n       \r\n      <dcConf assignActivate=\"300\" sync0Cycle=\"*1\" sync0Shift=\"-25000\"/>\r\n    </slave>\r\n  </master>\r\n</masters>\r\n\r\nIn the the component I read the information and use canfestival's SDO functions to configure the controller. They are no changes in the  SDO part of the canfestival.\r\n\r\nI rewrote the PDO part of canfestival since canfestival is not very useful in a master <---> many slaves environment.\r\n\r\nThe component implements DS301 and DS402 and exchanges the PDO data periodically (in my case every 8 ms). \r\n\r\nTo overcome my jitter problem I mentioned a few month ago, I wrote (a modified example)  a simple usespace xenomai task and send out sync can massage (i.e 8ms)\r\n\r\nrt_task_set_periodic(NULL, TM_NOW, 8000000);\r\n      //  previous = rt_timer_read();\r\n\r\n        while (1) {\r\n                rt_task_wait_period(NULL);\r\n                now = rt_timer_read();\r\n\t\t\r\n  \t\tret = rt_dev_sendto(s, (void *)&frame, sizeof(can_frame_t), 0,\r\n\t\t\t\t(struct sockaddr *)&to_addr, sizeof(to_addr));\r\n\t\tif (ret < 0) {\r\n\t    \t\tswitch (ret) {\r\n\t    \t\t\tcase -ETIMEDOUT:\r\n\t\t    \t\t\tprintf(\"rt_dev_send(to): timed out\\n\");\r\n\t\t\t\t\tbreak;\r\n\t    \t\t\tcase -EBADF:\r\n\t\t    \t\t\tprintf(\"rt_dev_send(to): aborted because socket was closed\\n\");\r\n\t\t\t\t\tbreak;\r\n\t    \t\t\tdefault:\r\n\t\t\t\t\tfprintf(stderr, \"rt_dev_sendx: %s\\n\", strerror(-ret));\r\n\t\t\t\t\tbreak;\r\n\t    \t\t\t}\r\n\t    \t\t//return;\r\n\t   \t}\r\n\r\n                /*\r\n                 * NOTE: printf may have unexpected impact on the timing of\r\n                 *       your program. It is used here in the critical loop\r\n                 *       only for demonstration purposes.\r\n                 */\r\n                //printf(\"Time since last turn: %ld.%06ld ms\\n\",\r\n                  //     (long)(now - previous) / 1000000,\r\n                    //   (long)(now - previous) % 1000000);\r\n                     //  previous = now;\r\n        }\r\n\r\nI also gave the task a specific CPU  :\r\n\r\n rt_task_create(&demo_task, \"trivial\", 0, 99, T_CPU(8));\r\n\r\n\r\nWith this program I'm able to produce the SYNC  message with a jitter about 10 us  verified on my oszi !!!!!\r\n\r\nI turned off the SYNC message in Canfestival, connected rtcan0 with rtcan1 ( a cable), run the sync program on rtcan0 and Canfestival on rtcan1.\r\n\r\nNow I'm trying to put all staff together in a hal component.  \r\n\r\nI'm not sure if they are any license issues if I publish my modified lcec-main.c. I'm also not very familiar with Github. When the component is more stable I can send you a zip-file.\r\n\r\nhelmut\r\n\r\n\r\n\r\n \r\n \r\n\r\n\r\n"}}