Ny structure. Start of the "main" branch
This commit is contained in:
BIN
Cards/EaserCAT-2000/Firmware/lib/soes/doc/images/esi_pdo.png
Executable file
BIN
Cards/EaserCAT-2000/Firmware/lib/soes/doc/images/esi_pdo.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
BIN
Cards/EaserCAT-2000/Firmware/lib/soes/doc/images/sii_pdo.png
Executable file
BIN
Cards/EaserCAT-2000/Firmware/lib/soes/doc/images/sii_pdo.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
50
Cards/EaserCAT-2000/Firmware/lib/soes/doc/soes.dox
Executable file
50
Cards/EaserCAT-2000/Firmware/lib/soes/doc/soes.dox
Executable file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* \mainpage Simple Open EtherCAT Slave or SOES
|
||||
*
|
||||
* \section start Tutorial
|
||||
* For a tutorial on SOES See tutorial.txt
|
||||
*
|
||||
* \section overview Overview
|
||||
* SOES is an EtherCAT slave stack written in c. Its purpose is to learn and
|
||||
* to use. All users are invited to study the source to get an understanding
|
||||
* how an EtherCAT slave function
|
||||
*
|
||||
* Features as of 1.0.0 :
|
||||
* - Address offset based HAL for easy ESC read/write access via any interface
|
||||
* - Mailbox with data link layer
|
||||
* - CoE
|
||||
* - Object dictionary
|
||||
* - SDO read and write for all sizes including segmented transfers
|
||||
* - Easy portable C-code suited for embedded applications
|
||||
* - Fixed PDO mapping
|
||||
* - FoE with bootstrap template
|
||||
* - Support for Little and Big endian targets.
|
||||
* - Polling for interrupts
|
||||
*
|
||||
* \section legal Legal notice
|
||||
* SOES Simple Open EtherCAT Slave \n
|
||||
* Copyright (C) 2007-2013 Arthur Ketels \n
|
||||
* Copyright (C) 2012-2013 rt-labs \n
|
||||
*
|
||||
* SOES is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* SOES is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* As a special exception, if other files instantiate templates or use macros
|
||||
* or inline functions from this file, or you compile this file and link it
|
||||
* with other works to produce a work based on this file, this file does not
|
||||
* by itself cause the resulting work to be covered by the GNU General Public
|
||||
* License. However the source code for this file must still be made available
|
||||
* in accordance with section (3) of the GNU General Public License.
|
||||
*
|
||||
* This exception does not invalidate any other reasons why a work based on
|
||||
* this file might be covered by the GNU General Public License.
|
||||
*
|
||||
* The EtherCAT Technology, the trade name and logo "EtherCAT" are the intellectual
|
||||
* property of, and protected by Beckhoff Automation GmbH.
|
||||
*/
|
||||
476
Cards/EaserCAT-2000/Firmware/lib/soes/doc/tutorial.txt
Executable file
476
Cards/EaserCAT-2000/Firmware/lib/soes/doc/tutorial.txt
Executable file
@@ -0,0 +1,476 @@
|
||||
/** \file
|
||||
|
||||
\section general General
|
||||
|
||||
The SOES is a library that provides the Micro Controller user application with
|
||||
the means to access the EtherCAT fieldbus communication environment:
|
||||
- EtherCAT State Machine
|
||||
- Mailbox Interfaces
|
||||
- Protocols
|
||||
- CoE
|
||||
- FoE + bootstrap template
|
||||
|
||||
Support for mailbox and protocols are typical examples when you need a slave
|
||||
stack to control the Application Layer of EtherCAT. The PDI used for such
|
||||
applications is either SPI or some Micro Controller Interface
|
||||
|
||||
The following sections show some basic examples on how to get the SOES up
|
||||
and running, as well as a lightweight example on howto design your slave.
|
||||
Since all code is local to the application or global variables, it is possible
|
||||
to tweak and optimize when possible.
|
||||
|
||||
Our target Application:
|
||||
- Inputs 40bit
|
||||
- One button 8bit
|
||||
- One encoder value 32bit
|
||||
- Outputs 8bit
|
||||
- LED 8bit
|
||||
- Parameters
|
||||
- Encoder settings
|
||||
- Slave commands
|
||||
- Reset counter
|
||||
|
||||
Now to translate and implement on top of SOES.
|
||||
|
||||
First look on the start up code. This example shows how to add a
|
||||
main function that will be called by startup code. In this example
|
||||
main's only purpose is to spawn two new tasks. One that executes
|
||||
SOES and one that control the ERROR LED. Some ESCs provided a pin
|
||||
for the RUN LED, some even for the ERROR LED, if it don't you can
|
||||
control them from the slave Micro Controller. We'll focus on the "soes" task.
|
||||
|
||||
\code
|
||||
|
||||
int main (void)
|
||||
{
|
||||
rprintp ("SOES (Simple Open EtherCAT Slave)\nsoes test\n");
|
||||
|
||||
/* task_spawn ("led_run", led_error, 15, 512, NULL); /
|
||||
task_spawn ("led_error", led_error, 15, 512, NULL);
|
||||
task_spawn ("soes", soes, 9, 1024, NULL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
\endcode
|
||||
|
||||
\section configuration Configuration
|
||||
The function soes is our EtherCAT slave device and can be split in 3 parts.
|
||||
Hardware Init, Software Init and Application loop. We will start with the
|
||||
Hardware Init.
|
||||
|
||||
- Hardware Init
|
||||
- esc_reset, special function used for ESC reset if no Physical
|
||||
EEPROM used. This is local to the Application not part of the generic
|
||||
ESC handling.
|
||||
- ESC_init, initialise SPI communication or similar
|
||||
- Wait for ESC is started, waiting for SPI to be up and running,
|
||||
we'll query the ESC register DL status if EEPROM loaded OK and PDI
|
||||
operational, eg. SPI OK.
|
||||
|
||||
\code
|
||||
|
||||
void soes (void *arg)
|
||||
{
|
||||
TXPDOsize = SM3_sml = sizeTXPDO ();
|
||||
RXPDOsize = SM2_sml = sizeRXPDO ();
|
||||
|
||||
esc_reset ();
|
||||
ESC_init ((void *)spi_name);
|
||||
|
||||
task_delay (tick_from_ms (200));
|
||||
|
||||
// wait until ESC is started up
|
||||
while ((ESCvar.DLstatus & 0x0001) == 0)
|
||||
{
|
||||
ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus,
|
||||
sizeof (ESCvar.DLstatus));
|
||||
ESCvar.DLstatus = etohs (ESCvar.DLstatus);
|
||||
}
|
||||
|
||||
// reset ESC to init state
|
||||
ESC_ALstatus (ESCinit);
|
||||
...
|
||||
}
|
||||
|
||||
\endcode
|
||||
|
||||
- Software Init
|
||||
- Reset the slave into Init state by writing AL Status register.
|
||||
- Clear Errors by writing AL Status Code register.
|
||||
- Stop the Application Layer, basically we disable the SyncManagers
|
||||
that implicitly block the data exchange.
|
||||
|
||||
\code
|
||||
|
||||
void soes (void *arg)
|
||||
{
|
||||
...
|
||||
while ((ESCvar.DLstatus & 0x0001) == 0)
|
||||
{
|
||||
ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus,
|
||||
sizeof (ESCvar.DLstatus));
|
||||
ESCvar.DLstatus = etohs (ESCvar.DLstatus);
|
||||
}
|
||||
|
||||
// reset ESC to init state
|
||||
ESC_ALstatus (ESCinit);
|
||||
ESC_ALerror (ALERR_NONE);
|
||||
ESC_stopmbx ();
|
||||
ESC_stopinput ();
|
||||
ESC_stopoutput ();
|
||||
|
||||
// application run loop
|
||||
while (1)
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
|
||||
- Application loop
|
||||
- ALevent handling, ALevent hold information on changes in ALControl or
|
||||
SyncManagers. ALControl for state changes and SyncManagers for changes written
|
||||
by EtherCAT in local memory mapped to active SyncManagers
|
||||
- ESC_state for state handling, such as state step up or down with correct
|
||||
error and acknowledge response.
|
||||
- Mailbox handler, generic support of mailboxes used by all Application Layer
|
||||
protocols.
|
||||
- On mailbox actions we'll also check if we need to use a specific protocol
|
||||
handler to handle the incoming or outgoing Mailbox data.
|
||||
|
||||
Up until the now we're using the SOES protocol stack without any application specific
|
||||
calls. Next up we'll look at the application Code, here named DIG_process ().
|
||||
|
||||
\code
|
||||
|
||||
void soes (void *arg)
|
||||
{
|
||||
...
|
||||
// application run loop
|
||||
while (1)
|
||||
{
|
||||
if((ESCvar.ALstatus & 0x0f) == ESCinit)
|
||||
{
|
||||
txpdomap = DEFAULTTXPDOMAP;
|
||||
rxpdomap = DEFAULTRXPDOMAP;
|
||||
txpdoitems = DEFAULTTXPDOITEMS;
|
||||
rxpdoitems = DEFAULTTXPDOITEMS;
|
||||
}
|
||||
ESC_read (ESCREG_LOCALTIME, (void *) &ESCvar.Time, sizeof (ESCvar.Time));
|
||||
ESCvar.Time = etohl (ESCvar.Time);
|
||||
|
||||
ESC_state ();
|
||||
if (ESC_mbxprocess ())
|
||||
{
|
||||
ESC_coeprocess ();
|
||||
ESC_foeprocess ();
|
||||
ESC_xoeprocess ();
|
||||
}
|
||||
DIG_process ();
|
||||
};
|
||||
}
|
||||
|
||||
\endcode
|
||||
|
||||
\section application Application
|
||||
The function DIG_process is the User part of the application and could be joined
|
||||
by more cyclic User functions for executing other parts of the application.
|
||||
The example code can be split in 2 parts
|
||||
- Outputs
|
||||
- Start by evaluating if we're in a state supporting update of outputs, eg.
|
||||
Operational state.
|
||||
- If we're in OP we can read the current PDO data in the 3-buffer SyncManager
|
||||
mapped to the output SM, the default is SyncManager2, we read the ESC RAM address
|
||||
of SM2 and store it at the local address of the local variable Wb.LED.
|
||||
We'll read RXPDOsize bytes to trigger a complete SyncManager read.
|
||||
- After local variables have been refreshed we basically write the local
|
||||
PDO variables to the User application, ex. a GPIO.
|
||||
- Basically this is the API of the SOES toward the User Application.
|
||||
- This function also include a watchdog mechanism, if triggered it will
|
||||
shutdown the outputs and trigger a state changes to safe operational.
|
||||
AlError is updated with cause of error to inform the Master.
|
||||
|
||||
\code
|
||||
|
||||
void RXPDO_update (void)
|
||||
{
|
||||
ESC_read (SM2_sma, &Wb.LED, RXPDOsize);
|
||||
}
|
||||
|
||||
void DIG_process (void)
|
||||
{
|
||||
if (App.state & APPSTATE_OUTPUT)
|
||||
{
|
||||
if (ESCvar.ALevent & ESCREG_ALEVENT_SM2) // SM2 trigger ?
|
||||
{
|
||||
RXPDO_update ();
|
||||
reset_wd ();
|
||||
gpio_set(GPIO_LED, Wb.LED & BIT(0));
|
||||
|
||||
}
|
||||
if (!wd_cnt)
|
||||
{
|
||||
ESC_stopoutput ();
|
||||
// watchdog, invalid outputs
|
||||
ESC_ALerror (ALERR_WATCHDOG);
|
||||
// goto safe-op with error bit set
|
||||
ESC_ALstatus (ESCsafeop | ESCerror);
|
||||
wd_trigger = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reset_wd ();
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
\endcode
|
||||
|
||||
- Inputs
|
||||
- Is handled a bit simpler than outputs but in reverse order, the slave will
|
||||
continue update the inputs in state Safe Operational.
|
||||
- Here we first read User application data from ex. GPIO and then write to
|
||||
local PDO variables.
|
||||
- After the local variables have been refreshed we write those to the current
|
||||
PDO data 3-buffer SyncManager mapped to the input SM, the default is SyncManager3.
|
||||
This way we update the ESC RAM address with User Application data accessed by
|
||||
the EtherCAT master.
|
||||
|
||||
\code
|
||||
|
||||
void TXPDO_update (void)
|
||||
{
|
||||
ESC_write (SM3_sma, &Rb.button, TXPDOsize);
|
||||
}
|
||||
|
||||
void DIG_process (void)
|
||||
{
|
||||
...
|
||||
Rb.button = gpio_get(GPIO_WAKEUP);
|
||||
Cb.reset_counter++;
|
||||
Rb.encoder = Cb.reset_counter;
|
||||
|
||||
TXPDO_update ();
|
||||
}
|
||||
|
||||
\endcode
|
||||
|
||||
\section ApplicationdataProcessdata ApplicationdataProcessdata
|
||||
To run application data through EtherCAT processdata we need to describe for
|
||||
the fieldbus what data we have and will read/write. For this we have 3 objects,
|
||||
the ESI file, SII-EEPROM and CoE Object Dictionary. The first 2 are mandatory
|
||||
and the third is a very convenient way of describing complex slaves.
|
||||
|
||||
Our strategy is to keep the ESI file and the SII-EEPROM as thin as possible to
|
||||
avoid duplication of data that need to be maintained. Both will hold the bare
|
||||
minimum of mandatory + optional data to pass CTT. Optional data will be
|
||||
included to tell EtherCAT that detailed information can be retrieved via CoE
|
||||
from the OD stored in the slave it self.
|
||||
|
||||
\section SII-EEPROM SII-EEPROM
|
||||
Snapshot from SII information matrix from EtherCAT communication slides.
|
||||
|
||||
\image html sii_pdo.png "Our target slave is Fixed PDO and OD"
|
||||
\image latex sii_pdo.png "Our target slave is Fixed PDO and OD" width=15cm
|
||||
|
||||
|
||||
\section ESI-file ESI-file
|
||||
Snapshot from ESI tree from EtherCAT communication slides.
|
||||
|
||||
\image html esi_pdo.png "mandatory and optional ESI data"
|
||||
\image latex esi_pdo.png "mandatory and optional ESI data" width=15cm
|
||||
|
||||
To briefly give a hint what are describe in the ESI and SII we're listing
|
||||
a set of included elements marked M for mandatory and O for optional.
|
||||
|
||||
\code
|
||||
- Vendor (M) , Describes the identity.
|
||||
- Id (M), Hex, EtherCAT Vendor ID, OD 1018.01
|
||||
- Name (M), NameType, Expedient vendor name
|
||||
- Descriptions (M), Describes the EtherCAT device(s) using elements.
|
||||
- Groups (M), Similar devices can be assigned to one group.
|
||||
- Group (M), One group groups similar devices with slightly different features
|
||||
- Type (M), A reference handle corresponding to the GroupType value in Description:Devices:Device:Group
|
||||
- Name (M), Name for this group show by a configuration tool
|
||||
- Devices (M), Element devices may describe one or several devices with their EtherCAT features such as SyncManagers, FMMUs and Dictionaries
|
||||
- Device (O), Holds all information about the device like syncmanagers and FMMU, object dictionary, data types and the PDO mapping and assign description
|
||||
- Device ATT: Physics (M),string, Physics at individual ports
|
||||
- Type (M), Device identity
|
||||
- Type ATT:ProductCode="#x98123467"
|
||||
- Type ATT:RevisionNo="#x00000001"
|
||||
- Name (M), Detailed name of device shown by a configuration tool (not used for identification)
|
||||
- GroupType (M), Reference to a group (described in element Groups) to which this device should be assigned to. Name of the handle used in element Groups:Group:Type
|
||||
- Fmmu (O), String to describe function, Outputs -> RxPDO, Inputs -> TxPDO , MBoxState -> FMMU is used to poll Input Mailbox
|
||||
- Sm (O), Description of SyncManager including start address and direction.
|
||||
- MBoxOut Mailbox Data Master -> Slave
|
||||
- MBoxIn Mailbox Data Slave -> Master
|
||||
- Outputs Process Data Master -> Slave
|
||||
- Inputs Process Data Slave -> master
|
||||
- Sm ATT:DefaultSize="128" , Size
|
||||
- Sm ATT:StartAddress="#x1000" , Start address
|
||||
- Sm ATT:ControlByte="#x26" , Settings , Bit [1][0] = 10, Operation mode Mailbox, 00 Buffered 3.
|
||||
- Sm ATT:Enable="1", Enabled
|
||||
- Mailbox (O), Description of available mailbox protocols
|
||||
- Mailbox ATT: DataLinkLayer="true", Support of Mailbox Data Link Layer is mandatory.
|
||||
- CoE (O), Device support CoE
|
||||
- CoE (O) ATT: SdoInfo="true" , SDO Information Service
|
||||
- CoE (O) ATT: CompleteAccess="false" , SDO complete access not supported
|
||||
- CoE (O) ATT: PdoUpload="true", PDO description uploaded from the slave's object dictionary and SyncManager length calculated based on the same
|
||||
- Dc (O), describes synchronization modes supported by the device.
|
||||
- OpMode (O), Definition of supported operation modes
|
||||
- Name (M), Internal Handle of operation mode
|
||||
- Desc (O(M)), description of operation mode, recommended, Free Run (no sync), SM Synchronous, DC Synchronous
|
||||
- AssignActive (M), Value of Latch and Sync Control registers
|
||||
- Eeprom (O, use is mandatory)
|
||||
- Data (M)
|
||||
Or
|
||||
- ByteSize (M), Byte Size of connected EEPROM device
|
||||
- ConfigData (M), First 7 words of EEPROM, Configuration Areas
|
||||
- BootStrap (O), Start address and length of mailboxes for BootStrap
|
||||
\endcode
|
||||
|
||||
So to describe the application we use CoE and Object Dictionary. The mapping between
|
||||
Object Dictionary and the User Application are done via local variables defined as
|
||||
user types. The Object Dictionary itself is stored in a matrix where all
|
||||
the indexes are listed. Every index then have a submatrix with its subindex.
|
||||
|
||||
\section ObjectDictionary ObjectDictionary
|
||||
The Object Dictionary used as example follow the CANopen DS301 ranges.
|
||||
|
||||
- 0x0000 - 0x0FFF, Data Type Area
|
||||
- 0x1000 - 0x1FFF, Communication Area
|
||||
- 0x2000 - 0x5FFF, Manufacture specific area
|
||||
- 0x6000 - 0x6FFF, Input area
|
||||
- 0x7000 - 0x7FFF, Output area
|
||||
- 0x8000 - 0x8FFF, Configuration area
|
||||
- 0x9000 - 0x9FFF, Information area
|
||||
- 0xA000 - 0xAFFF, Diagnosis Area
|
||||
- 0xB000 - 0xBFFF, Service Transfer Area
|
||||
- 0xC000 - 0xEFFF, Reserved Area
|
||||
- 0xF000 - 0xFFFF, Device Area
|
||||
|
||||
RxPDO , 0x1600 - 0x17FF
|
||||
TxPDO , 0x1A00 - 0x1BFF
|
||||
|
||||
Example, on how the the OD index are linked.
|
||||
Top index, SyncManagers Communication Types. In index 0 the 0x04 indicates we have 4
|
||||
SyncManagers defined. Every SyncManager is assigned a type, in index 1-4, we have standard
|
||||
settings SM0 = 1, SM1 = 2, SM2 = 3, SM3 = 4 from ETG 1000.6, 5.6.7.4.
|
||||
- 0, Unused
|
||||
- 1, MailBox Receive, master to slave
|
||||
- 2, MailBox Send, slave to master
|
||||
- 3, Processdata output, master to slave
|
||||
- 4, Processdata input, slave to master
|
||||
|
||||
\code
|
||||
objectlist.h
|
||||
FLASHSTORE _objectlist SDOobjects[] =
|
||||
...
|
||||
{0x1C00, OTYPE_ARRAY, 4, 0, &acName1C00[0], &SDO1C00[0]},
|
||||
|
||||
FLASHSTORE _objd SDO1C00[] =
|
||||
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x04, nil},
|
||||
{0x01, DTYPE_UNSIGNED8, 8, ATYPE_R, &acName1C00_01[0], 0x01, nil},
|
||||
{0x02, DTYPE_UNSIGNED8, 8, ATYPE_R, &acName1C00_02[0], 0x02, nil},
|
||||
{0x03, DTYPE_UNSIGNED8, 8, ATYPE_R, &acName1C00_03[0], 0x03, nil},
|
||||
{0x04, DTYPE_UNSIGNED8, 8, ATYPE_R, &acName1C00_04[0], 0x04, nil}
|
||||
|
||||
\endcode
|
||||
|
||||
SyncManagers channels 0-31 are listed in SDO1C10-SDO1C2F. If we look
|
||||
at SyncManager channel 2, we see.
|
||||
|
||||
- Type 3, Processdata output, master to slave
|
||||
|
||||
It got one RxPDO index 0x1600 connected, and the submatrix for 0x1600 link
|
||||
one PDO object index 0x7000 subindex 1. The output object 0x70000108 give
|
||||
you the index 0x7000, subindex 1 and PDO object length 1(byte).
|
||||
|
||||
\code
|
||||
objectlist.h
|
||||
FLASHSTORE _objd SDO1C12[] =
|
||||
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x01, nil},
|
||||
{0x01, DTYPE_UNSIGNED16, 16, ATYPE_R, &acNameMO[0], 0x1600, nil}
|
||||
};
|
||||
|
||||
FLASHSTORE _objd SDO1600[] =
|
||||
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x01, nil},
|
||||
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_R, &acNameMO[0], 0x70000108, nil}
|
||||
};
|
||||
|
||||
\endcode
|
||||
|
||||
At PDO level we make the connection between the local application and
|
||||
the object dictionary. For all subindex in the PDO the last element
|
||||
is the address to the local variable.
|
||||
|
||||
\code
|
||||
|
||||
objectlist.h
|
||||
FLASHSTORE _objd SDO7000[] =
|
||||
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x01, nil},
|
||||
{0x01, DTYPE_UNSIGNED8, 8, ATYPE_RW, &acName7000_01[0], 0, &(Wb.LED)}
|
||||
};
|
||||
|
||||
utypes.h
|
||||
typedef struct
|
||||
{
|
||||
uint8 LED;
|
||||
} _Wbuffer;
|
||||
|
||||
\endcode
|
||||
|
||||
Beside SyncManager to PDO mapping we also have mandatory data as
|
||||
|
||||
0x1000 Device Type
|
||||
0x1018 Object Identity
|
||||
0x10C0 SyncManager Communication Type, as we used as top index when
|
||||
figuring out our PDOs in the Object Dictionary.
|
||||
|
||||
For a complete description of the object dictionary you can get guidance
|
||||
by the ETG1000.6 EcatAlProtocols
|
||||
|
||||
A useful feature is the Asynchronous use of SDO parameters. In the example
|
||||
we have Parameter set holding an encoder scale value, just for show we also
|
||||
have a read only mirror value of the encoder scale. Parameters defined as a
|
||||
RW SDO parameter and can be written/read by SDO Download or Upload. In
|
||||
addition there is a ESC_objecthandler Hook on SDO Download where you can
|
||||
add additional logic, ex. we execute the mirror of the encoder scale value
|
||||
by assigning the encoder scale value to the mirror.
|
||||
|
||||
\code
|
||||
|
||||
objectlist.h
|
||||
FLASHSTORE _objd SDO7100[] =
|
||||
{ {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x02, nil},
|
||||
{0x01, DTYPE_UNSIGNED32, 32, ATYPE_RW, &acName7100_01[0], 0, &(encoder_scale)},
|
||||
{0x02, DTYPE_UNSIGNED32, 32, ATYPE_R, &acName7100_02[0], 0, &(encoder_scale_mirror)}
|
||||
};
|
||||
|
||||
soes.c
|
||||
void ESC_objecthandler (uint16 index, uint8 subindex)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
...
|
||||
case 0x7100:
|
||||
{
|
||||
switch (subindex)
|
||||
{
|
||||
case 0x01:
|
||||
{
|
||||
encoder_scale_mirror = encoder_scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
\endcode
|
||||
This tutorial is just one way of doing it.
|
||||
Enjoy and happy coding!
|
||||
|
||||
Andreas Karlsson, rt-labs AB, www.rt-labs.com
|
||||
*/
|
||||
Reference in New Issue
Block a user