Comments (10)
Hi @MarcVonS,
You could using SDO write to send commands, but this is usually done via PDO (self._master.slaves[i].output = value).
Furtuantly I have a Trinamic TMCM-1617 at hand. The following minimalistic script works very well to simply turn the motor at a given speed.
I hope this is can be adapte do your drive card.
"""Running a TMCM-1617 in Profile velocity mode.
Remarks:
* You need to adapt <your network adapter id> first.
* This script assumes that only the TMCM-1617 is connected to the master.
* Pressing CTRL+C whill stopt the motor and exit the script.
* PDO configuration is kept at its default configuration.
* All other CoE objects are supposed to have it's default values.
* Add a `print(convert_input_data(tmcm1617.input).velocity_actual_value)` in the `while 1` loop to
monitor the current velocity.
Note: Make sure to constantly send process data to the drive, otherwise it goes to SafeOP Error state.
"""
import pysoem
import time
import ctypes
tmcm1617 = None
class InputPdo(ctypes.Structure):
_pack_ = 1
_fields_ = [
('modes_of_operation_display', ctypes.c_int8),
('statusword', ctypes.c_uint16),
('position_demand_value', ctypes.c_int32),
('position_actual_value', ctypes.c_int32),
('velocity_demand_value', ctypes.c_int32),
('velocity_actual_value', ctypes.c_int32),
('torque_demand_value', ctypes.c_int32),
('torque_actual_value', ctypes.c_int32),
('digital_input', ctypes.c_uint32),
]
class OutputPdo(ctypes.Structure):
_pack_ = 1
_fields_ = [
('modes_of_operation', ctypes.c_int8),
('controlword', ctypes.c_uint16),
('target_position', ctypes.c_int32),
('target_velocity', ctypes.c_int32),
('target_torque', ctypes.c_int32),
('digital_output', ctypes.c_uint32),
]
modes_of_operation = {
'No mode': 0,
'Profile position mode': 1,
'Profile velocity mode': 3,
'Homing mode': 6,
'Cyclic synchronous position mode': 8,
'Cyclic synchronous velocity mode': 9,
'Cyclic synchronous torque mode': 10,
}
def convert_input_data(data):
return InputPdo.from_buffer_copy(data)
def tmcm1617_config_func(slave_pos):
global tmcm1617
# limit maximum current
tmcm1617.sdo_write(0x2003, 0, (2000).to_bytes(length=4, byteorder='little', signed=False))
# set torque control P value
tmcm1617.sdo_write(0x2041, 1, (50).to_bytes(length=2, byteorder='little', signed=False))
# set torque control I value
tmcm1617.sdo_write(0x2041, 2, (20).to_bytes(length=2, byteorder='little', signed=False))
# set motor type = BLDC
tmcm1617.sdo_write(0x2050, 0, bytes([3]))
# set commutation mode = Hall sensors
tmcm1617.sdo_write(0x2055, 0, bytes([2]))
# inverse hall direction
tmcm1617.sdo_write(0x2070, 2, bytes([1]))
# tune hall PHI_E offset
tmcm1617.sdo_write(0x2070, 4, (10500).to_bytes(length=2, byteorder='little', signed=True))
def main():
global tmcm1617
master = pysoem.Master()
master.open('<your network adapter id>') # someting like '\\Device\\NPF_{B4B7A38F-7DEB-43AF-B787B7-EABADE43978EA}' under Windows
if master.config_init() > 0:
tmcm1617 = master.slaves[0]
tmcm1617.config_func = tmcm1617_config_func
master.config_map()
if master.state_check(pysoem.SAFEOP_STATE, 50_000) == pysoem.SAFEOP_STATE:
master.state = pysoem.OP_STATE
master.write_state()
master.state_check(pysoem.OP_STATE, 5_000_000)
if master.state == pysoem.OP_STATE:
output_data = OutputPdo()
output_data.modes_of_operation = modes_of_operation['Profile velocity mode']
output_data.target_velocity = 500 # RPM
for control_cmd in [6, 7, 15]:
output_data.controlword = control_cmd
tmcm1617.output = bytes(output_data) # that is the actual change of the PDO output data
master.send_processdata()
master.receive_processdata(1_000)
time.sleep(0.01)
try:
while 1:
master.send_processdata()
master.receive_processdata(1_000)
time.sleep(0.01)
except KeyboardInterrupt:
print('stopped')
# zero everything
tmcm1617.output = bytes(len(tmcm1617.output))
master.send_processdata()
master.receive_processdata(1_000)
else:
print('failed to got to op state')
else:
print('failed to got to safeop state')
master.state = pysoem.PREOP_STATE
master.write_state()
else:
print('no device found')
master.close()
if __name__ == '__main__':
main()
from pysoem.
Hello bnjmnp,
big thanks for your answer!
Since tuesday I modify your code and was able to communicate with the TMCM-3213.
But in the Operational mode after sending the velocity value the drives aren't moving.
I also got no Error.
When you read the value of "modes of operation display" during process there should be a 3 printed right?
If I check it I get the answer 24 and this is not a mode.
Do I see it right that the entries from InputPDO()
and OutputPDO()
must match the entries from the SDO that I got with the "read_sdo_info.py"-skript?
This is the moddified code maybe you see a mistake in it:
"""Running a TMCM-3213 in Profile velocity mode.
Remarks:
* You need to adapt <your network adapter id> first.
* This script assumes that only the TMCM-3213 is connected to the master.
* Pressing CTRL+C whill stopt the motor and exit the script.
* PDO configuration is kept at its default configuration.
* All other CoE objects are supposed to have it's default values.
* Add a `print(convert_input_data(tmcm3213.input).velocity_actual_value)` in the `while 1` loop to
monitor the current velocity.
Note: Make sure to constantly send process data to the drive, otherwise it goes to SafeOP Error state.
"""
import pysoem
import time
import ctypes
import struct
tmcm3213 = None
class InputPdo(ctypes.Structure):
_pack_ = 1
_fields_ = [
('Axis0_modes_of_operation_display_1', ctypes.c_int8),
('Axis1_modes_of_operation_display_2', ctypes.c_int8),
('Axis2_modes_of_operation_display_3', ctypes.c_int8),
('Axis0_statusword_1', ctypes.c_uint16),
('Axis1_statusword_2', ctypes.c_uint16),
('Axis2_statusword_3', ctypes.c_uint16),
('Axis0_velocity_actual_value_1', ctypes.c_int32),
('Axis1_velocity_actual_value_2', ctypes.c_int32),
('Axis2_velocity_actual_value_3', ctypes.c_int32),
]
class OutputPdo(ctypes.Structure):
_pack_ = 1
_fields_ = [
('Axis0_Modes_of_Operation_1', ctypes.c_int8),
('Axis1_Modes_of_Operation_2', ctypes.c_int8),
('Axis2_Modes_of_Operation_3', ctypes.c_int8),
('Axis0_controlword_1', ctypes.c_uint16),
('Axis1_controlword_2', ctypes.c_uint16),
('Axis2_controlword_3', ctypes.c_uint16),
('Axis0_target_position_1', ctypes.c_int32),
('Axis1_target_position_2', ctypes.c_int32),
('Axis2_target_position_3', ctypes.c_int32),
('Axis0_target_velocity_1', ctypes.c_int32),
('Axis1_target_velocity_2', ctypes.c_int32),
('Axis2_target_velocity_3', ctypes.c_int32),
('digital_output', ctypes.c_uint32),
]
modes_of_operation = {
'No mode': 0,
'Profile position mode': 1,
'Profile velocity mode': 3,
'Homing mode': 6,
'Cyclic synchronous position mode': 8,
'Cyclic synchronous velocity mode': 9,
}
def convert_input_data(data):
return InputPdo.from_buffer_copy(data)
def tmcm3213_config_func(slave_pos):
global tmcm3213
# limit maximum current
tmcm3213.sdo_write(0x2003, 0, struct.pack('B', 175))
#tmcm3213.sdo_write(0x2203, 0, struct.pack('B', 175))
#tmcm3213.sdo_write(0x2403, 0, struct.pack('B', 175))
# Switch Settings
#tmcm3213.sdo_write(0x2005, 0, struct.pack('I', 3))
#tmcm3213.sdo_write(0x2205, 0, struct.pack('I', 3))
#tmcm3213.sdo_write(0x2405, 0, struct.pack('I', 3))
# limit maximum acceleration
tmcm3213.sdo_write(0x6083, 0, (5600).to_bytes(length=4, byteorder='little', signed=True))
#tmcm3213.sdo_write(0x6883, 0, (5600).to_bytes(length=4, byteorder='little', signed=True))
#tmcm3213.sdo_write(0x7083, 0, (5600).to_bytes(length=4, byteorder='little', signed=True))
def main():
global tmcm3213
master = pysoem.Master()
master.open('enp1s0') # Connecting to drivercard
if master.config_init() > 0: # If a Slave was fount
tmcm3213 = master.slaves[0] # Slave 0 definition as tmcm3213
tmcm3213.config_func = tmcm3213_config_func # Configuration of TMCM-3213 watch #67
master.config_map() # Send configuration -> SAFE_OP
if master.state_check(pysoem.SAFEOP_STATE, 50_000) == pysoem.SAFEOP_STATE: # SAFE_OP set? (TMCM-3213)
master.state = pysoem.OP_STATE # OP_STATE in Master
master.write_state() # Send new Status OP_STATE
master.state_check(pysoem.OP_STATE, 5_000_000) # Controll if OP_STATE is set
if master.state == pysoem.OP_STATE: # If OP_STATE reached
output_data = OutputPdo()
output_data.modes_of_operation = modes_of_operation['Profile velocity mode'] #Set PV-Mode
output_data.Axis0_target_velocity_1 = 500 #Set velocity
for control_cmd in [6, 7, 15]: # 6= ready_to_switch_on / 7=Switched_ON / 15= Operation_Enabled
output_data.Axis0_controlword_1 = control_cmd
tmcm3213.output = bytes(output_data) # change of the PDO output data
master.send_processdata() # send Data
master.receive_processdata(1_000) # recieve Data
time.sleep(0.01)
try:
while 1:
master.send_processdata() # send Data loop
master.receive_processdata(1_000) # recieve Data loop
print(convert_input_data(tmcm3213.input).Axis0_velocity_actual_value_1) #output Info
time.sleep(0.01)
except KeyboardInterrupt:
print('stopped')
# zero everything
tmcm3213.output = bytes(len(tmcm3213.output))
master.send_processdata() # send Data
master.receive_processdata(1_000) # recieve Data
else:
print('failed to got to op state')
else:
print('failed to got to safeop state')
master.state = pysoem.PREOP_STATE
master.write_state()
else:
print('no device found')
master.close()
if __name__ == '__main__':
main()
from pysoem.
Looking in the ESI file of the TMCM-3213 at the RxPdo and TxPdo element, the default PDO configuration should be:
class InputPdo(ctypes.Structure):
_pack_ = 1
_fields_ = [
('statusword_1', ctypes.c_uint16),
('modes_of_operation_display_1', ctypes.c_int8),
('position_actual_value_1', ctypes.c_int32),
('velocity_actual_value_1', ctypes.c_int32),
('statusword_2', ctypes.c_uint16),
('modes_of_operation_display_2', ctypes.c_int8),
('position_actual_value_2', ctypes.c_int32),
('velocity_actual_value_2', ctypes.c_int32),
('statusword_3', ctypes.c_uint16),
('modes_of_operation_display_3', ctypes.c_int8),
('position_actual_value_3', ctypes.c_int32),
('velocity_actual_value_3', ctypes.c_int32),
]
class OutputPdo(ctypes.Structure):
_pack_ = 1
_fields_ = [
('controlword_1', ctypes.c_int16),
('modes_of_operation_1', ctypes.c_uint8),
('target_position_1', ctypes.c_int32),
('target_velocity_1', ctypes.c_int32),
('controlword_2', ctypes.c_int16),
('modes_of_operation_2', ctypes.c_uint8),
('target_position_2', ctypes.c_int32),
('target_velocity_2', ctypes.c_int32),
('controlword_3', ctypes.c_int16),
('modes_of_operation_3', ctypes.c_uint8),
('target_position_3', ctypes.c_int32),
('target_velocity_3', ctypes.c_int32),
]
I hope this is it .. cannot say for sure.
from pysoem.
Oh, and be careful in that line:
output_data.modes_of_operation = modes_of_operation['Profile velocity mode'] #Set PV-Mode
in your code. The .modes_of_operation field does not exist. Just .Axis0_Modes_of_Operation_1.
from pysoem.
Oh man it works!
Big thanks to you!!
from pysoem.
Hi,
I have an ethercat driver and most thing similar your code. I entegrated your code to my driver but i have some problems.
1-"OutputPdo" and "InputPdo" how it works? There is no index in it and i dont now how to use it because all parameters my driver have index.
2-I can reach OP-STATE but motor moving 1 or 2 second and stop but no problem with OP-STATE
3-While entagrating code i have to add "dc_sync" to my code why u dont use
I need some help @bnjmnp @MarcVonS and thank you already.
Best regards.
from pysoem.
Hi @zopcuk,
1-
OutputPDO and InputPDO are composed by standard parameter 0x1C12 (OutputPDO) and 0x1C13 (InputPDO) and parameter 0x1600 to 0x17FF (OutputPDO) and 0x1A00 to 0x1BFF (InputPDO).
Checkout the ESI file for your drive. There you will have the "RxPdo" (OutputPDO) and the "TxPdo" (InputPDO) element which will give you the default PDO mapping and configuration.
Taken the example of the TMCM-1617.
This
<RxPdo Fixed="0" Sm="2">
<Index>#x1600</Index>
<Name>RxPDO 1</Name>
<Entry>
<Index>#x6060</Index>
<SubIndex>#x0</SubIndex>
<BitLen>8</BitLen>
<Name>Modes of Operation</Name>
<DataType>SINT</DataType>
</Entry>
<Entry>
<Index>#x6040</Index>
<SubIndex>#x0</SubIndex>
<BitLen>16</BitLen>
<Name>Controlword</Name>
<DataType>UINT</DataType>
</Entry>
<Entry>
<Index>#x607a</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Target Position</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x60ff</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Target Velocity</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x6071</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Target Torque</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x2703</Index>
<SubIndex>#x1</SubIndex>
<BitLen>32</BitLen>
<Name>Physical Outputs</Name>
<DataType>UDINT</DataType>
</Entry>
</RxPdo>
relates to:
class OutputPdo(ctypes.Structure):
_pack_ = 1
_fields_ = [
('modes_of_operation', ctypes.c_int8),
('controlword', ctypes.c_uint16),
('target_position', ctypes.c_int32),
('target_velocity', ctypes.c_int32),
('target_torque', ctypes.c_int32),
('digital_output', ctypes.c_uint32),
]
And this
<TxPdo Fixed="0" Sm="3">
<Index>#x1A00</Index>
<Name>TxPDO 1</Name>
<Entry>
<Index>#x6061</Index>
<SubIndex>#x0</SubIndex>
<BitLen>8</BitLen>
<Name>Modes of Operation Display</Name>
<DataType>SINT</DataType>
</Entry>
<Entry>
<Index>#x6041</Index>
<SubIndex>#x0</SubIndex>
<BitLen>16</BitLen>
<Name>Statusword</Name>
<DataType>UINT</DataType>
</Entry>
<Entry>
<Index>#x6062</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Position Demand Value</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x6064</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Position Actual</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x606b</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Velocity Demand Value</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x606c</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Velocity Actual</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x6074</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Torque Demand Value</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x6077</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Torque Actual</Name>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x2702</Index>
<SubIndex>#x0</SubIndex>
<BitLen>32</BitLen>
<Name>Device Digital Inputs</Name>
<DataType>UDINT</DataType>
</Entry>
</TxPdo>
relates to
class InputPdo(ctypes.Structure):
_pack_ = 1
_fields_ = [
('modes_of_operation_display', ctypes.c_int8),
('statusword', ctypes.c_uint16),
('position_demand_value', ctypes.c_int32),
('position_actual_value', ctypes.c_int32),
('velocity_demand_value', ctypes.c_int32),
('velocity_actual_value', ctypes.c_int32),
('torque_demand_value', ctypes.c_int32),
('torque_actual_value', ctypes.c_int32),
('digital_input', ctypes.c_uint32),
]
2-
you could print out the "statusword" by replacing print(convert_input_data(tmcm3213.input).Axis0_velocity_actual_value_1)
with print(convert_input_data(tmcm3213.input).statusword)
.
Maybe this will give you some information.
Does your drive really remain in OP state when the motors stop, you should simply check this by taking a look at the Status LEDs. Flashing means PreOP or SafeOP, continuously on means OP stat.
3-
Again checking out the ESI file, one can see for the TMCM-1617 that we can use "SyncManager Synchronisation" (SM-Synchron) OR "DC Synchronisation" (DC-Synchron).
<Dc>
<OpMode>
<Name>Synchron</Name>
<Desc>FreeRun/SM-Synchron</Desc>
<AssignActivate>#x0</AssignActivate>
</OpMode>
<OpMode>
<Name>DC</Name>
<Desc>DC-Synchron</Desc>
<AssignActivate>#x300</AssignActivate>
<CycleTimeSync0 Factor="1">0</CycleTimeSync0>
<ShiftTimeSync0>0</ShiftTimeSync0>
<CycleTimeSync1 Factor="1">0</CycleTimeSync1>
<ShiftTimeSync1>0</ShiftTimeSync1>
</OpMode>
</Dc>
In DC synchronisation it can get difficult if you don't send_processdata
in sync with the DC Sync-Pulse, thus we better don't use it with pysoem.
from pysoem.
Hi @bnjmnp thank you for answer,
1- I think i understand OutputPDO and InputPdo.
I have 4 RxPDO and 4 TxPDO and i chose first ones.
1st RxPDO
<!-- 1st RxPDO -->
<RxPdo Fixed="0">
<Index>#x1600</Index>
<Name>1st RxPDO Mapping</Name>
<Exclude>#x1601</Exclude>
<Exclude>#x1602</Exclude>
<Exclude>#x1603</Exclude>
<Entry>
<Index>#x6040</Index>
<SubIndex>0</SubIndex>
<BitLen>16</BitLen>
<Name>Control Word</Name>
<Comment>object 0x6040:0</Comment>
<DataType>UINT</DataType>
</Entry>
<Entry>
<Index>#x607A</Index>
<SubIndex>0</SubIndex>
<BitLen>32</BitLen>
<Name>TargetPosition</Name>
<Comment>object 0x607A:0</Comment>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x60FF</Index>
<SubIndex>0</SubIndex>
<BitLen>32</BitLen>
<Name>TargetVelocity</Name>
<Comment>object 0x60FF:0</Comment>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x6071</Index>
<SubIndex>0</SubIndex>
<BitLen>16</BitLen>
<Name>TargetTorque</Name>
<Comment>object 0x6071:0</Comment>
<DataType>INT</DataType>
</Entry>
</RxPdo>
1st TxPDO
<!--1st TxPDO -->
<TxPdo Fixed="0">
<Index>#x1a00</Index>
<Name>1st TxPDO Mapping</Name>
<Exclude>#x1a01</Exclude>
<Exclude>#x1a02</Exclude>
<Exclude>#x1a03</Exclude>
<Entry>
<Index>#x6041</Index>
<SubIndex>0</SubIndex>
<BitLen>16</BitLen>
<Name>Status Word</Name>
<Comment>object 0x6041:0</Comment>
<DataType>UINT</DataType>
</Entry>
<Entry>
<Index>#x6064</Index>
<SubIndex>0</SubIndex>
<BitLen>32</BitLen>
<Name>ActualPosition</Name>
<Comment>object 0x6064:0</Comment>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x606C</Index>
<SubIndex>0</SubIndex>
<BitLen>32</BitLen>
<Name>Velocity actual value</Name>
<Comment>object 0x606C:0</Comment>
<DataType>DINT</DataType>
</Entry>
<Entry>
<Index>#x6077</Index>
<SubIndex>0</SubIndex>
<BitLen>16</BitLen>
<Name>ActualTorque</Name>
<Comment>object 0x6077:0</Comment>
<DataType>INT</DataType>
</Entry>
</TxPdo>
I am plannig reorganize InputPDO and OutputPDO with my RxPDO and TxPDO.
Do you think there is anything I should pay attention to?
2- I cant print status right now because error. First i have to edit InputPDO and OutputPDO straightly.
But my driver have 7 segment display and shows status and mode. It tells me driver remain OP-STATE
3- I think i have only DC-Synchron mode
İs this cause any problem with pysoem?
<Dc Unknown64Bit="true">
<OpMode>
<Name>DC</Name>
<Desc>DC-Synchron</Desc>
<AssignActivate>#x300</AssignActivate>
<CycleTimeSync0 Factor="1">0</CycleTimeSync0>
<ShiftTimeSync0>0</ShiftTimeSync0>
</OpMode>
</Dc>
from pysoem.
Hi @bnjmnp,
Finally managed to run. I can control now my driver and motor with no problem.
Your answer enlightened me. Thank you again.
from pysoem.
Hi @bnjmnp ,
I attached my ESI file here
I have 2 motors (Axis1,Axis2) , I don't know how to write InputPdo and OutputPdo
Could you help me to move the motors ?
Thank you for your support.
from pysoem.
Related Issues (20)
- Failed to write pdo? HOT 3
- Creating a link between master and slave HOT 2
- Ethercat Ring Topology HOT 1
- How to install soem to raspberry pi 4 ? HOT 1
- IAI Motor Controller (PCON-CB) - Not Getting to OP State Correctly HOT 6
- config_init append slaves to CdefMaster slaves attribute, but never clean it HOT 1
- IO-Link Ethercat module (EL6224) HOT 2
- Returning PDO frame late (Windows) HOT 2
- Handle Safety HOT 2
- ConnectionError: could not open interface on Ubuntu HOT 3
- Motion control HOT 1
- read and write PDOS question HOT 2
- Add meaning of 'network adapter ID' to documentation HOT 2
- Script crashes when Python debugger inspects `CdefSlave`
- OD version bug HOT 1
- maybe a BUGm needs deeg in HOT 1
- How to pack / unpack single `BIT`s in PDO `input` / `output` HOT 3
- Open function returns always None HOT 2
- slave.write_eeprom() bug? HOT 2
- Transfer `pysoem` into the `OpenEtherCATsociety` Github group HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pysoem.