analogdevicesinc / TMC-API

TRINAMIC's IC API

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TMC5160 and Raspeberry PI

thalesfsp opened this issue · comments

Hi! I'm trying to follow this blog post, but applied to the TMC5160 BOB. I cloned the latest version of the API, and made a few adjustments in the code, but I'm having problems with the init function.

The signature presented in the blog post, void TMC5130_init(unsigned char motor) is different from the API void tmc5130_init(TMC5130TypeDef *tmc5130, uint8_t channel, ConfigurationTypeDef *config, const int32_t *registerResetState)

I've limited knowledge on C, and in electronics. I searched around the web for examples of this new signature, and how to use/call that, but unfortunately did not find.

Follow my current project.c file:

#include "SPI.h"
#include "tmc/ic/TMC5160/TMC5160.h"
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

static void myStateDemoMachine(int steps, int velocity);

int main(int argc, char **argv)
{
	// start  SPI
		printf("Initialize SPI..\n");	
		SPI_init();
		printf("..done\n");	
	
	remove("demo.s"); // exit demo mode	

	int value;
	switch(argv[1][0]) // process arguments, first argument is the command, others are values
	{
		case 'i': // initialize
			printf("Initialize driver..\n");	
			tmc5160_init(0);			
		break;
			
		case 'r': // rotate
			printf("Rotate with %ipps..\n", atoi(argv[2]));	
			tmc5160_rotate(0, atoi(argv[2]));
		break;
		
		case '0': //stop
			printf("Stop motor..\n");	
			tmc5160_rotate(0, 0);
		break;
		
		case 't': // move to position
			printf("Move to absolute absolute %d with velocity %ipps..\n", atoi(argv[2]), atoi(argv[3]));	
			tmc5160_left(0,0);										// stop motor
			tmc5160_writeInt(0,TMC5160_VMAX, abs(atoi(argv[3])));	// set velocity
			// tmc5160_moveTo(TMC5160TypeDef *tmc5160, int32_t position, uint32_t velocityMax)
			tmc5160_moveTo(0, 0,  atoi(argv[2]));						// set target
		break;
		
		case 'b': // move by number of steps
			printf("Move to by %d steps with velocity %ipps..\n", atoi(argv[2]), atoi(argv[3]));	
			tmc5160_left(0,0);										// stop motor
			tmc5160_writeInt(0,TMC5160_VMAX, abs(atoi(argv[3])));	// set velocity
			tmc5160_moveBy(0, 0,  atoi(argv[2]));						// set target
		break;
		
		case 'g': // get register value
			value = tmc5160_readInt(0,atoi(argv[2]));			//read from address
			printf("Read from address 0x%2x =%i[int] = %08x[hex] = %f[double])\n", atoi(argv[2]), (int) value, (int) value, (double) value);
		break;
		
		case 's': // set register value
			tmc5160_writeInt(0,atoi(argv[2]), atoi(argv[3]));			//write to address
			printf("Write to address 0x%2x<=%i[int] = %08x[hex] = %f[double])\n", atoi(argv[2]), (int)  atoi(argv[3]), (int)  atoi(argv[3]), (double)  atoi(argv[3]));
		break;
		
		case 'd': // start demo
			printf("Demo: Move back and forth by %d steps with velocity %ipps..\n", atoi(argv[2]), atoi(argv[3]));

			close(open("demo.s", O_RDWR | O_CREAT, 0777)); // generate semaphore-file
			
			while(access("demo.s", F_OK ) != -1) // as long as demo semaphore-file exists
			{
				myStateDemoMachine(atoi(argv[2]),abs(atoi(argv[3]))); // call demo code
				usleep(500); 
			}			
		break;
		
		default:
			printf("Unknown command\n");	
		break;
	}
	
	// end SPI
		printf("De-initialize SPI..\n");
		SPI_deinit();
		printf("..done\n");	
}

enum { DEMO_STATE_INIT, DEMO_STATE_MOVE_RIGHT, DEMO_STATE_WAIT_RIGHT, DEMO_STATE_MOVE_LEFT, DEMO_STATE_WAIT_LEFT};

static void myStateDemoMachine(int steps, int velocity)
{ // simple state for moving back and forth
	
	static int state		= DEMO_STATE_INIT;
	static int nextState	= DEMO_STATE_INIT; 

	
	switch(state)
	{
		case DEMO_STATE_INIT:
			tmc5160_moveBy(0, 0, 0);
			tmc5160_writeInt(0,TMC5160_VMAX, velocity);
			nextState = DEMO_STATE_MOVE_RIGHT;			
		break;
		
		case DEMO_STATE_MOVE_RIGHT:
			printf("Move right by %d steps with velocity %ipps..\n", steps, velocity);
			tmc5160_moveBy(0, 0,steps);
			nextState = DEMO_STATE_WAIT_RIGHT;
		break;	
		
		case DEMO_STATE_WAIT_RIGHT:
			usleep(20000);
			if(tmc5160_readInt(0,TMC5160_RAMPSTAT) & (1<<9)) // if bit 9 in RAMPSTAT is set (position_reached)
			{
				nextState = DEMO_STATE_MOVE_LEFT;
			}
		break;		
		
		case DEMO_STATE_MOVE_LEFT:			
			printf("Move left by %d steps with velocity %ipps..\n", -steps, velocity);
			tmc5160_moveBy(0, 0,-steps);
			nextState = DEMO_STATE_WAIT_LEFT;
		break;

		case DEMO_STATE_WAIT_LEFT:
			usleep(20000);
			if(tmc5160_readInt(0,TMC5160_RAMPSTAT) & (1<<9)) // if bit 9 in RAMPSTAT is set (position_reached)
			{
				nextState = DEMO_STATE_MOVE_RIGHT; 
			}
		break;		
	}	
	state = nextState;	
}

Thank you!

Hi,
the source code for the Raspberry 3B has, per default, nothing to do with the TMC-API. It has its own coherent project, hence the different functions and function signatures. So you have to decide if you want to use the functions presented there or if you want to switch to using the TMC-API, which is possible of course.

If you want to use the TMC-API:

The TMC5160TypeDef is just a structure for storing all neccessary information needed by the API (for e.g. register shadowing). You can look at it like a logical instance of an IC. You can look inside this structure, but you dont need to. The API takes care of it. Same with ConfigurationTypeDef instances.

So what you have to do is basically create instances of TMC5160TypeDef and ConfigurationTypeDef (one each for every individual IC) somewhere in your project.c file, pass both as pointers to the tmc5130_init function and give it a channel number. You can assign these numbers arbitrarily, they are used to differentiate between communications channels later on. If you just have one channel, in this case one SPI channel, you can just use 0.
As registerResetState you can just use tmc5160_defaultRegisterResetState provided by the TMC-API.

After that, just implement the function tmc5160_readWriteArray(...), which is needed by the API to read / write using your SPI.

A reference implementation for the TMC5160-EVAL can be found here. This can be applied to the TMC5160-BOB similarly.

Hello, @Lionheart1810! Thank you for your help! Can you help one more time providing me example of instances for both TMC5160TypeDef and ConfigurationTypeDef? What is required to be defined in these both instances? Finally, I would like to learn more about it. Would you be available for 30mins to join a chat and review my case? Cheers!

Example instances are already in the linked reference implementation. They are created as simple as

ConfigurationTypeDef config;
TMC5160TypeDef TMC5160;

After creation, you don't actually have to fiddle with its contents at all. Generally speaking, ConfigurationTypeDef offers state information and register shadowing to your IC instance.
Also, remember to take care of some registers you might need to set to certain values to get your specific setup running.
Yes I guess I can take some time to look over it. Which platform though?

@Lionheart1810 I have Keybase, Zoom and Google Meet. You choose. How can I DM you? Email? Cheers and really thank you for your time and help, I appreciate that! Cheers!

Send me an E-Mail to kugis@trinamic.com

Thank you! I will reach you! Cheers!

Hello @Lionheart1810! I did message you :)