Shop OBEX P1 Docs P2 Docs Learn Events
The Teacup Port - A Work In Progress - 3D Printer Firmware - Page 8 — Parallax Forums

The Teacup Port - A Work In Progress - 3D Printer Firmware

1234568

Comments

  • idbruceidbruce Posts: 6,197
    edited 2015-03-23 10:16
    Dave
    Now the simulator mode works with 2 cogs. This can be easily adapted to driving a real 3D printer by changing the functions in the simulator directory.

    So what now? Are you going to make it functional?

    Referring to the project that I uploaded in Post #210...... Considering all the rearranging I did on the source code, perhaps the incorrect readings are due to these changes. I think I will shorten the GCODE file and see if it pushes the steppers.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-23 11:01
    idbruce wrote: »
    So what now? Are you going to make it functional?
    In theory I would just have to change the READ, WRITE, SET_INPUT and SET_OUTPUT functions in simulator.c to make it functional. I have some stepper motors, but I've never played around with them. Maybe it time to start wiring up some things. :)

    I've attached a zip file containing the code with all the changes I made. The nice thing is that I've made hardly any changes to the the main portion of the teacup code, and almost all the changes are to the files in the simulator directory.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-23 11:15
    Dave
    I have some stepper motors, but I've never played around with them. Maybe it time to start wiring up some things.

    Absolutely!!! However, be forewarned, your life may change. For better or maybe worse :):)
  • idbruceidbruce Posts: 6,197
    edited 2015-03-23 11:44
    I think I will shorten the GCODE file and see if it pushes the steppers.

    No luck with that one.

    I think I am going to take a break from trying to get this to work and study the math of the firmware for a bit.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-26 04:43
    I had seriously thought about giving up on Teacup, and was exploring the idea of creating my own firmware from scratch, but I have come to the realization that starting from scratch is insane. The truth of the matter is, I now know the Teacup firmware pretty darn well, but just not well enough to make it work yet. So instead of abandoning it, I have decided to learn more about it.

    I believe my last attempt was very close to being successful, but I definitely missed something, and I have further come to the conclusion, that in my current arrangement of the code, concerning the program split that I installed, locks are only required for reading and writing to the queue. I further believe that the primary cog is in good working order, because it basically just keeps reading characters and adds items to the queue, but it should lock the queue when adding items.

    The queue monitor cog, basically the movement cog, needs to lock the queue while reading it. After reading the queue, this cog should perform the action described by the queue entry. When it has finished processing one entry, it should remove the entry from the queue, and grab the next one. So on and so forth...

    One way or the other, it is very, very close now and there is no point in giving up on it. I was just getting a bit irritated and disgusted with the project.

    I have come up with an idea or two for cutting down the size, so hopefully that will help.

    To help me nail down the remaining problems, I am going to take the last build and cut it down to the absolute minimum, and work from there.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-01 08:41
    I have temporarily and perhaps permanently abandoned the actual Teacup port, and have steered the Forger firmware down a different path, such as creating my own firmware. At this point, things appear to look fairly promising, but still a bit iffy. However, a subtantial amount of memory can be regained when unnecessary print commands are deleted, as well as unnecessary definitions.

    The definitions for axes Z & E are currently fictitious for testing purposes.

    To run this project, simply set your sd pin assignments within config.h, under the heading "Propeller Memory Card Assignments" and feed it some GCODE. Besides that, you really shouldn't have any pin problems, because no other pins have been set yet.

    Now comes the hard part, which is firguring out all the math to implement this code: http://forums.parallax.com/showthread.php/159926-Introducing-quot-SyncroStepper-quot-Syncronization-For-Multi-Axis-Machines. My biggest worry is now cogs, because I believe I will definitely be over by implementing this code, especially with serial input.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-01 15:26
    Pertaining to the uploaded project of the previous post, I just noticed that some of the values shown on the terminal, for the E axis, are incorrect. I will have to study these results a little more in depth to determine where the error is coming from and if there are additional errors.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-01 16:11
    Referring to my last post, I think I know where I went wrong.

    Consider the following code:
    	if(current_gcode.E_NUM > previous_gcode.E_NUM)
    	{
    		current_gcode.E_DISTANCE = current_gcode.E_NUM - previous_gcode.E_NUM;
    		current_gcode.E_DIR = E_INC_DIR;
    		current_gcode.E_STEPS = 
    			calc_steps_required(current_gcode.E_DISTANCE, E_STEPS_PER_MM);
    	}     
    	else if(current_gcode.E_NUM < previous_gcode.E_NUM)
    	{
    		current_gcode.E_DISTANCE = previous_gcode.E_NUM - current_gcode.E_NUM;
    		current_gcode.E_DIR = E_DEC_DIR;
    		current_gcode.E_STEPS = 
    			calc_steps_required(current_gcode.E_DISTANCE, E_STEPS_PER_MM);
    	} 
    	else
    	{
    		current_gcode.E_DISTANCE = 0;
    		current_gcode.E_DIR = previous_gcode.E_DIR;
    		current_gcode.E_STEPS = 0;
    	}
    

    This only shows the conditional statements for the E axis, but it would also apply to all axes not shown. During the first two conditions, I should also be ensuring that current_gcode.E_NUM is not equal to 0. So I believe the proceeding code should look more like this:
    	if(current_gcode.E_NUM != 0 && current_gcode.E_NUM > previous_gcode.E_NUM)
    	{
    		current_gcode.E_DISTANCE = current_gcode.E_NUM - previous_gcode.E_NUM;
    		current_gcode.E_DIR = E_INC_DIR;
    		current_gcode.E_STEPS = 
    			calc_steps_required(current_gcode.E_DISTANCE, E_STEPS_PER_MM);
    	}     
    	else if(current_gcode.E_NUM != 0 && current_gcode.E_NUM < previous_gcode.E_NUM)
    	{
    		current_gcode.E_DISTANCE = previous_gcode.E_NUM - current_gcode.E_NUM;
    		current_gcode.E_DIR = E_DEC_DIR;
    		current_gcode.E_STEPS = 
    			calc_steps_required(current_gcode.E_DISTANCE, E_STEPS_PER_MM);
    	} 
    	else
    	{
    		current_gcode.E_DISTANCE = 0;
    		current_gcode.E_DIR = previous_gcode.E_DIR;
    		current_gcode.E_STEPS = 0;
    	}
    
  • idbruceidbruce Posts: 6,197
    edited 2015-04-01 17:46
    I believe the corrections mentioned in the previous post has taken care of the errors that I was seeing. I am now uploading a corrected version. This version also displays the required direction of rotation for the motors.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-02 02:09
    @idbruce:
    As to the size problem:
    I have not studied the code of TeaCup yet, though it would seem to me if you redid all the control stuff in PASM, making each section fit into a single COG you could use a lot less memory.

    Use one COG for all the motor controls (under 300 instructions to control 3 steppers and one servo). Use one cog for all the sensors. Then you have only the G-Code stuff in SPIN, and possibly some communication stuff, and the load hub ram that was used to load the PASM code that is then put into COG mem can be reused for buffers or what ever.

    This is why my firmware is mostly in PASM, and none of it needs to be kept in Hub mem.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 06:23
    Over the last couple of days, I have been taking a break from my parser and working a little more on Teacup. In an effort to cut down the size, I trimmed the unnecessary fat from the adafruit_ads1015 library and I have eliminated propellerized.h. It may not work yet, but it now looks like a Propeller application instead of an AVR application :)

    As mentioned ealier, Teacup is written pretty darn lean, and there is not a whole lot of code that you can remove and still remain functional. I could try eliminating some of the supported G and M commands, but I really do not want to do that. So right now, it is propably as small as it is going to get, and it is still too large. However, I do have a new strategy.

    My new strategy is similar to my current stragegy, in the fact that the program will be split in two. There are several significant portions of code, but the two main ones are parsing and processing, with the queue being the middleman. As is the current situation, the split will be at the queue. However due to memory concerns, it cannot remain as it is and this is where the new strategy comes into play. It is a basic concept and it should not be to hard to implement. I will be taking the sd reading, serial reading, and GCODE parsing and placing them on one Propeller chip and the rest of the code, which all pertains to processing, will be placed on another Propeller chip. And the only thing that will pass from one chip to the other will be the queue. So one chip will create the queue and the other chip will process the queue.

    I believe this should do the trick, but perhaps the processing end may still be too large for one Propeller chip. Only testing will tell.

    By adding another Propeller chip, I also gain another advantage, which is the removal of the Propeller Memory Card from the main controller board, thus opening up several IO pins, so that all homing and limit switches can be utilized. In all honesty, it is looking pretty promising, and as mentioned, it should not require too many changes on the current controller board.
  • Mark_TMark_T Posts: 1,981
    edited 2015-04-03 07:51
    idbruce wrote: »
    I will be taking the sd reading, serial reading, and GCODE parsing and placing them on one Propeller chip and the rest of the code, which all pertains to processing, will be placed on another Propeller chip. And the only thing that will pass from one chip to the other will be the queue. So one chip will create the queue and the other chip will process the queue.

    A thought - would it be possible to write the queued data to SDcard/SRAM and use two passes, needing only one Prop ?
  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 08:13
    Mark

    Since my last post, I have been trying to make an actual split and I have come to the conclusion, that a split is not possible, like I thought it would be. That firmware is so tightly intermingled, it is just simply unbelievable. Teacup is truly a brilliant peace of code work, but it will be very difficult to actually port it to the Propeller, unless of course Dave does something with the simulator end of things.

    The main problem is the way the M codes and various G codes are handled. Some of them are never added to the queue, which was an oversight on my part. If they had added everything to the queue for processing, I believe it would have been a breeze. I do not believe there is a work around for this obstacle.

    Besides all the work I have invested, it is really a shame that I could not get this to work for the Propeller. I think it would have been a good thing for Parallax.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 08:25
    Please be advised that I am definitely abandoning the Teacup port and all efforts thereof. However, I will be going forward with the Forger firmware, but not under the source of Teacup.

    If anyone is interested in my stopping point, along with further obstacles that need to be overcome, I would be more than happy to discuss these issues, as well as providing the latest project build.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-03 08:56
    idbruce wrote: »
    Please be advised that I am definitely abandoning the Teacup port and all efforts thereof. However, I will be going forward with the Forger firmware, but not under the source of Teacup.

    If anyone is interested in my stopping point, along with further obstacles that need to be overcome, I would be more than happy to discuss these issues, as well as providing the latest project build.
    That is OK. If it may interest you, in the next couple of days I will be posting the firmware I am re-writing for my 3D printer, that uses a single Propeller.

    I am debating weather I will continue to process the G-Code in the firmware, or if I will instead use a more compact command structure to send to the printer and process the G-Code on the host system.

    The original firmware I wrote was mostly in PASM, the rewrite is almost all spin. The Original did have the G-Code processor in the Propeller, though I think it better to process that on the host side (still open to debate).

    It will be a while before I am able to test the rewrite, as it is just bits and pieces at the moment, though if you would like I can start a thread to step through my work in progress.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 09:14
    David
    If it may interest you, in the next couple of days I will be posting the firmware I am re-writing for my 3D printer, that uses a single Propeller.

    I am always interested in seeing code that operates machinery, but what I am really interested in is the processing of steps with Bresenham's line drawing algorithm.

    I will be starting a new thread soon for my current parser and processor.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-03 09:31
    idbruce wrote: »
    David



    I am always interested in seeing code that operates machinery, but what I am really interested in is the processing of steps with Bresenham's line drawing algorithm.

    I will be starting a new thread soon for my current parser and processor.
    Well I have already started the thread, though code will come later, hopefully today for the Stepper object anyway.

    As to the line drawing, you are in luck. My stepper object includes a simplified implementation for the XY plane. I did this to simplify some of the work in controlling the 3D printer.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-03 09:58
    Bruce, it seems like compiling the G-Code into a stepper file might be the way to go. You could break up the Teacup code into two programs. The first one would write out the information that is currently going to the queue, and the second program would read the queue file and generate the stepper commands. You could run this from one of the OSes that are available for the Prop. I would suggest using spinix, but there are a few other OSes that you can choose from. Or you can run it without an OS by making the first program start the second one when it's done. Of course another way to do it is to run the G-Code compiler on a PC, and then run the stepper program on the Prop.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 10:41
    Dave

    Yea that won't work with Teacup, it is a lame duck at this point. If you refer to Post #224, you will see that I state that the M codes never make it to the queue and it relies on gcode_process to do a lot of the work, which makes splitting it, almost an impossibility.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-05 16:42
    Dave

    In reference to your Post #213, READ, WRITE, SET_INPUT and SET_OUTPUT....

    As you know, the definitions were in arduino.h, which was then altered to propellerized.h. During an attempt at code reduction, propellerized.h was completely eliminated. Without the use of the simulator, there were three files using these functions which were forger.c, pinio.c, and pinio.h. These three files were modified to remove all macros and utilize propeller functions from simpletools.h.

    From the main file
    void io_init(void)
    {
    	// setup I/O pins
    
    	// X Stepper
    	set_direction(X_STEP_PIN, 1);
    	set_output(X_STEP_PIN, 0);
    
    	set_direction(X_DIR_PIN, 1);
    	set_output(X_DIR_PIN,  0);	
    
    	#ifdef X_MIN_PIN
    		set_direction(X_MIN_PIN, 0);
    		set_output(X_MIN_PIN, 0);
    	#endif
    
    	#ifdef X_MAX_PIN
    		set_direction(X_MAX_PIN, 0);
    		set_output(X_MAX_PIN, 0);
    	#endif
    
    	// Y Stepper
    	set_direction(Y_STEP_PIN, 1);
    	set_output(Y_STEP_PIN, 0);
    
    	set_direction(Y_DIR_PIN, 1);
    	set_output(Y_DIR_PIN, 0);
    
    	#ifdef Y_MIN_PIN
    		set_direction(Y_MIN_PIN, 0);
    		set_output(Y_MIN_PIN, 0);
    	#endif
    
    	#ifdef Y_MAX_PIN
    		set_direction(Y_MAX_PIN, 0);
    		set_output(Y_MAX_PIN, 0);
    	#endif
    
    	// Z Stepper
    	set_direction(Z_STEP_PIN, 1);
    	set_output(Z_STEP_PIN, 0);
    	
    	set_direction(Z_DIR_PIN, 1);
    	set_output(Z_DIR_PIN, 0);	
    
    	#ifdef Z_MIN_PIN
    		set_direction(Z_MIN_PIN, 0);
    		set_output(Z_MIN_PIN, 0);
    	#endif
    
    	#ifdef Z_MAX_PIN
    		set_direction(Z_MAX_PIN, 0);
    		set_output(Z_MAX_PIN, 0);
    	#endif
    
    	// E Stepper
    	set_direction(E_STEP_PIN, 1);
    	set_output(E_STEP_PIN, 0);
    
    	set_direction(E_DIR_PIN, 1);
    	set_output(E_DIR_PIN, 0);
    
    	// Common Stepper Enable
    	#ifdef STEPPER_ENABLE_PIN
    
    		set_direction(STEPPER_ENABLE_PIN, 1);
    
    		#ifdef STEPPER_INVERT_ENABLE
    			set_output(STEPPER_ENABLE_PIN, 0);
    		#else
    			set_output(STEPPER_ENABLE_PIN, 1);
    		#endif
    			
    	#endif
    
    	// X Stepper Enable
    	#ifdef X_ENABLE_PIN
    
    		set_direction(X_ENABLE_PIN, 1);
    
    		#ifdef X_INVERT_ENABLE
    			set_output(X_ENABLE_PIN, 0);
    		#else
    			set_output(X_ENABLE_PIN, 1);
    		#endif
    		
    	#endif
    
    	// Y Stepper Enable
    	#ifdef Y_ENABLE_PIN
    
    		set_direction(Y_ENABLE_PIN, 1);
    
    		#ifdef Y_INVERT_ENABLE
    			set_output(Y_ENABLE_PIN, 0);
    		#else
    			set_output(Y_ENABLE_PIN, 1);
    		#endif
    		
    	#endif
    
    	// Z Stepper Enable
    	#ifdef Z_ENABLE_PIN
    
    		set_direction(Z_ENABLE_PIN, 1);
    
    		#ifdef Z_INVERT_ENABLE
    			set_output(Z_ENABLE_PIN, 0);
    		#else
    			set_output(Z_ENABLE_PIN, 1);
    		#endif
    		
    	#endif
    
    	// E Stepper Enable
    	#ifdef E_ENABLE_PIN
    
    		set_direction(E_ENABLE_PIN, 1);
    
    		#ifdef E_INVERT_ENABLE
    			set_output(E_ENABLE_PIN, 0);
    		#else
    			set_output(E_ENABLE_PIN, 1);
    		#endif
    		
    	#endif
    
    	#ifdef	STEPPER_ENABLE_PIN
    		power_off();
    	#endif
    }
    

    pinio.c
    // Edited 3/17/2015 - 4 space tab spacing
    
    #include "pinio.h"
    #include "simpletools.h"
    
    static char ps_is_on = 0;
    
    /// step/psu timeout
    volatile uint8_t psu_timeout = 0;
    
    void power_on()
    {
    	if(ps_is_on == 0)
    	{
    		#ifdef PS_ON_PIN
    
    		set_direction(PS_ON_PIN, 1);
    		set_output(PS_ON_PIN, 0);
    
    		pause(500);
    
    		#endif
    
    		#ifdef PS_MOSFET_PIN
    
    		set_output(PS_MOSFET_PIN, 1);
    
    		pause(10);
    
    		#endif
    
    		ps_is_on = 1;
    	}
    
    	psu_timeout = 0;
    }
    
    void power_off()
    {
    	stepper_disable();
    	x_disable();
    	y_disable();
    	z_disable();
    	e_disable();
    
    	#ifdef PS_ON_PIN
    
    	set_direction(PS_ON_PIN, 0);
    
    	#endif
    
    	#ifdef PS_MOSFET_PIN
    
    	set_output(PS_MOSFET_PIN, 0);
    
    	#endif
    
    	ps_is_on = 0;
    }
    

    pinio.h
    // Edited 3/17/2015 - 4 space tab spacing
    
    /** \file
     \brief I/O primitives - step, enable, direction, endstops etc
    */
    
    #ifndef _PINIO_H
    #define _PINIO_H
    
    #include "config.h"
    #include "simpletools.h"
    
    /*
    Power
    */
    /// psu_timeout is set to zero when we step, and increases over time so we can
    /// turn the motors off when they've been idle for a while.
    /// A second function is to guarantee a minimum on time of the PSU.
    /// Timeout counting is done in clock.c.  It is used inside and outside of
    /// interrupts, which is why it has been made volatile
    extern volatile uint8_t psu_timeout;
    
    static void power_init(void);
    
    inline void power_init(void)
    {
    	#ifdef PS_MOSFET_PIN
    
    	set_output(PS_MOSFET_PIN, 0);
    	set_direction(PS_MOSFET_PIN, 1);
    
    	#endif
    }
    
    void power_on(void);
    void power_off(void);
    
    ///////////////////////////////////////////////////////////////////////////////
    /*
    X Stepper
    */
    #define _x_step(st) set_output(X_STEP_PIN, st)
    #define x_step() _x_step(1)
    
    #ifndef X_INVERT_DIR
    	#define x_direction(dir) set_output(X_DIR_PIN, dir)
    #else
    	#define x_direction(dir) set_output(X_DIR_PIN, (dir)^1)
    #endif
    
    #ifdef X_MIN_PIN
    	#ifndef X_INVERT_MIN
    		#define x_min() (get_output(X_MIN_PIN)?1:0)
    	#else
    		#define x_min() (get_output(X_MIN_PIN)?0:1)
    	#endif
    #else
    	#define x_min() (0)
    #endif
    
    #ifdef X_MAX_PIN
    	#ifndef X_INVERT_MAX
    		#define x_max() (get_output(X_MAX_PIN)?1:0)
    	#else
    		#define x_max() (get_output(X_MAX_PIN)?0:1)
    	#endif
    #else
    	#define x_max() (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    Y Stepper
    */
    #define _y_step(st) set_output(Y_STEP_PIN, st)
    #define y_step() _y_step(1)
    
    #ifndef Y_INVERT_DIR
    	#define y_direction(dir) set_output(Y_DIR_PIN, dir)
    #else
    	#define y_direction(dir) set_output(Y_DIR_PIN, (dir)^1)
    #endif
    
    #ifdef Y_MIN_PIN
    	#ifndef Y_INVERT_MIN
    		#define y_min() (get_output(Y_MIN_PIN)?1:0)
    	#else
    		#define y_min() (get_output(Y_MIN_PIN)?0:1)
    	#endif
    #else
    	#define y_min() (0)
    #endif
    
    #ifdef Y_MAX_PIN
    	#ifndef Y_INVERT_MAX
    		#define y_max() (get_output(Y_MAX_PIN)?1:0)
    	#else
    		#define y_max() (get_output(Y_MAX_PIN)?0:1)
    	#endif
    #else
    	#define y_max() (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    Z Stepper
    */
    #if defined Z_STEP_PIN && defined Z_DIR_PIN
    	#define _z_step(st) set_output(Z_STEP_PIN, st)
    	#define z_step() _z_step(1)
    
    	#ifndef Z_INVERT_DIR
    		#define z_direction(dir) set_output(Z_DIR_PIN, dir)
    	#else
    		#define z_direction(dir) set_output(Z_DIR_PIN, (dir)^1)
    	#endif
    #else
    	#define _z_step(x) do {} while (0)
    	#define z_step() do {} while (0)
    	#define z_direction(x) do {} while (0)
    #endif
    
    #ifdef Z_MIN_PIN
    	#ifndef Z_INVERT_MIN
    		#define z_min() (get_output(Z_MIN_PIN)?1:0)
    	#else
    		#define z_min() (get_output(Z_MIN_PIN)?0:1)
    	#endif
    #else
    	#define z_min() (0)
    #endif
    
    #ifdef Z_MAX_PIN
    	#ifndef Z_INVERT_MAX
    		#define z_max() (get_output(Z_MAX_PIN)?1:0)
    	#else
    		#define z_max() (get_output(Z_MAX_PIN)?0:1)
    	#endif
    #else
    	#define z_max() (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    E Stepper
    */
    #if defined E_STEP_PIN && defined E_DIR_PIN
    	#define _e_step(st) set_output(E_STEP_PIN, st)
    
    	#define e_step() _e_step(1)
    
    	#ifndef E_INVERT_DIR
    		#define e_direction(dir) set_output(E_DIR_PIN, dir)
    	#else
    		#define e_direction(dir) set_output(E_DIR_PIN, (dir)^1)
    	#endif
    #else
    	#define _e_step(st) do {} while (0)
    	#define e_step() do {} while (0)
    	#define e_direction(dir) do {} while (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    End Step - All Steppers
    (so we don't have to delay in interrupt context)
    */
    #define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0)
    
    /*
    Stepper Enable Pins
    */
    #ifdef STEPPER_ENABLE_PIN
    	#ifdef STEPPER_INVERT_ENABLE
    		#define stepper_enable() set_output(STEPPER_ENABLE_PIN, 0)
    		#define stepper_disable() set_output(STEPPER_ENABLE_PIN, 1)
    	#else
    		#define stepper_enable() set_output(STEPPER_ENABLE_PIN, 1)
    		#define stepper_disable() set_output(STEPPER_ENABLE_PIN, 0)
    	#endif
    #else
    	#define stepper_enable() do {} while (0)
    	#define stepper_disable() do {} while (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    X Stepper Enable
    */
    #ifdef X_ENABLE_PIN
    	#ifdef X_INVERT_ENABLE
    		#define x_enable() set_output(X_ENABLE_PIN, 0)
    		#define x_disable() set_output(X_ENABLE_PIN, 1)
    	#else
    		#define x_enable() set_output(X_ENABLE_PIN, 1)
    		#define x_disable() set_output(X_ENABLE_PIN, 0)
    	#endif
    #else
    	#define x_enable() do {} while (0)
    	#define x_disable() do {} while (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    Y Stepper Enable
    */
    #ifdef Y_ENABLE_PIN
    	#ifdef Y_INVERT_ENABLE
    		#define y_enable() set_output(Y_ENABLE_PIN, 0)
    		#define y_disable() set_output(Y_ENABLE_PIN, 1)
    	#else
    		#define y_enable() set_output(Y_ENABLE_PIN, 1)
    		#define y_disable() set_output(Y_ENABLE_PIN, 0)
    	#endif
    #else
    	#define y_enable() do {} while (0)
    	#define y_disable() do {} while (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    Z Stepper Enable
    */
    #ifdef Z_ENABLE_PIN
    	#ifdef Z_INVERT_ENABLE
    		#define z_enable() set_output(Z_ENABLE_PIN, 0)
    		#define z_disable() set_output(Z_ENABLE_PIN, 1)
    	#else
    		#define z_enable() set_output(Z_ENABLE_PIN, 1)
    		#define z_disable() set_output(Z_ENABLE_PIN, 0)
    	#endif
    #else
    	#define z_enable() do { } while (0)
    	#define z_disable() do { } while (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    E Stepper Enable
    */
    #ifdef E_ENABLE_PIN
    	#ifdef E_INVERT_ENABLE
    		#define e_enable() set_output(E_ENABLE_PIN, 0)
    		#define e_disable() set_output(E_ENABLE_PIN, 1)
    	#else
    		#define e_enable() set_output(E_ENABLE_PIN, 1)
    		#define e_disable() set_output(E_ENABLE_PIN, 0)
    	#endif
    #else
    	#define e_enable() do {} while (0)
    	#define e_disable() do {} while (0)
    #endif
    ///////////////////////////////////////////////////////////////////////////////
    /*
    Endstops
    */
    static void endstops_on(void) __attribute__ ((always_inline));
    
    inline void endstops_on(void)
    {
    	#ifdef X_MIN_PIN
    		set_output(X_MIN_PIN, 1);
    	#endif
    
    	#ifdef X_MAX_PIN
    		set_output(X_MAX_PIN, 1);
    	#endif
    
    	#ifdef Y_MIN_PIN
    		set_output(Y_MIN_PIN, 1);
    	#endif
    
    	#ifdef Y_MAX_PIN
    		set_output(Y_MAX_PIN, 1);
    	#endif
    
    	#ifdef Z_MIN_PIN
    		set_output(Z_MIN_PIN, 1);
    	#endif
    
    	#ifdef Z_MAX_PIN
    		set_output(Z_MAX_PIN, 1);
    	#endif
    }
    
    static void endstops_off(void) __attribute__ ((always_inline));
    
    inline void endstops_off(void)
    {
    	#ifdef X_MIN_PIN
    		set_output(X_MIN_PIN, 0);
    	#endif
    
    	#ifdef X_MAX_PIN
    		set_output(X_MAX_PIN, 0);
    	#endif
    
    	#ifdef Y_MIN_PIN
    		set_output(Y_MIN_PIN, 0);
    	#endif
    
    	#ifdef Y_MAX_PIN
    		set_output(Y_MAX_PIN, 0);
    	#endif
    
    	#ifdef Z_MIN_PIN
    		set_output(Z_MIN_PIN, 0);
    	#endif
    
    	#ifdef Z_MAX_PIN
    		set_output(Z_MAX_PIN, 0);
    	#endif
    }
    ///////////////////////////////////////////////////////////////////////////////
    
    #endif /* _PINIO_H */
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-06 05:46
    Bruce, I don't understand your point. Does your code work with all the changes you made? I made minimal changes, and my code works. You would just have to make a few more additional changes to my code to get it to drive pins. So what were you trying to say in your last post? I don't get it.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-06 06:37
    Dave
    In theory I would just have to change the READ, WRITE, SET_INPUT and SET_OUTPUT functions in simulator.c to make it functional.

    I was just telling you how I changed my files to eliminate the macros completely.
    Does your code work with all the changes you made?

    LOL I wish it did.
    I made minimal changes, and my code works.

    I do not know what you are seeing that I am not. When I run your program with the terminal, I simply get a blue screen. When I type, the terminal displays the characters, but that is it. What's working? I basically have a blue screen. I still don't get it. How are you verifying that it is working?
    You would just have to make a few more additional changes to my code to get it to drive pins.

    What are the remaining changes that need to be done?
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-06 07:08
    Dave Hein wrote: »
    ... change the READ, WRITE, SET_INPUT and SET_OUTPUT functions in simulator.c to make it functional.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-06 07:34
    LOL Thats funny... okay

    What about config.h? Just swap it out for my config.h?
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-06 07:37
    Bruce, I think I've given you enough assistance. If you are going to mock me then just forget it.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-06 07:53
    Dave

    I was not mocking you... I was laughing at the fact that I missed the most important part of your post... but okay
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-06 08:05
    I guess I misinterpreted your "LOL". Yes, of course you have to change config.h to match your hardware. And if you're going to add SD support you may need to remove some features from the Teacup code to get it to fit. Given the difficulties you've had with this code it may be best that you try a different approach. The Teacup code was written for the AVR, and it has a lot of ugly AVR stuff in it. It might be better to just cut your losses and team up with David Saunders. He seems to have a working approach.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-06 08:23
    Dave Hein wrote: »
    I guess I misinterpreted your "LOL". Yes, of course you have to change config.h to match your hardware. And if you're going to add SD support you may need to remove some features from the Teacup code to get it to fit. Given the difficulties you've had with this code it may be best that you try a different approach. The Teacup code was written for the AVR, and it has a lot of ugly AVR stuff in it. It might be better to just cut your losses and team up with David Saunders. He seems to have a working approach.
    While I do thank you, it is taking me a bit of time to do my rewrite. I am only have done with the native command processor, and just begining on the G-Code to native command converter (which has to be fast enough to keep ahead of the serial input, as G-Code is a lot bigger than the native command language I created).

    Thank you for the confidence though.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-07 07:52
    While taking a break from my pity party, I thought I would take a moment to summarize the current standing of this project and upload the latest build. As it stands now, I do believe the attached archive is the closest that I have come to a working version, however it is still not working.

    The attached archive will generate three (3) warnings during the build process. These warnings are as follows:
    gcode_process.c: In function 'process_gcode_command':
    gcode_process.c:792:23: warning: unused variable 'triggered' [-Wunused-variable]
    gcode_process.c:791:23: warning: unused variable 'open' [-Wunused-variable]
    gcode_process.c:447:11: warning: unused variable 'i' [-Wunused-variable]
    

    And these warnings particularly apply to the processing of M2/M84 and M119 commands within gcode_process.c. Commands M2/M84 have a commented loop, which blocks the use of the "i" variable, and command M119 generates unused variable warnings because limit switches have not been defined in config.h, therefore the variables "open" and "triggered" are currently unused.

    Without going into too much detail, this project has reorganized the Teacup firmware in an attempt to bypass the use of interrupts. Basically the main cog creates the movement queue and another cog attempts to read and process the movement queue. In an effort to provide the cleanest project possible for future endeavors, I have removed some of the previous programming, in which I attempted to make the shared variables and structs volatile, however this generated a bunch of warnings due to memcpy. It is my understanding that in order for these variables and structs to be shared between cogs, they must be volatile.

    As well as removing some previous programming, I have also reestablished some of the previously removed programming, but more particularly, the original source and header files for the ADS1015 ADC.

    While I do believe that my theory of operation should work, the biggest obstacle at this point is overcoming the memory issue, because I cannot troubleshoot any further without overcoming this barrier. The code responsible for processing the queue and movement, resides in queue_monitor.c. Within queue_monitor.c a while loop is currently commented out, because it causes the code to fail severly. At this point, I assuming that this is due to insuffient stack space, until I get the opportunity to prove otherwise. However I suppose the failing code could also be attributed to the code that I am attempting to run, however this code closely matches the original Teacup code. The currently alloted stack size for the queue_monitor cog is a mere 150 int(s), and I just know this is way to small, because this cog handles a lot of code. The current build comes in at "Code Size 28,536 bytes (31,176 total)".

    EDIT: Known And Assumed Cog Usage
    1) Main (Known)
    2) ADS1015 ADC (Assumed)
    3) SD Card (Assumed)
    4) Queue Monitor (Known)
    5) Clock Timer (Known)
    6) Full Duplex Serial (Currently Unused, If Enabled Known)


    I am looking for any reasonable ideas to decrease program size,
    which would allow a larger stack size for the queue_monitor cog.


    ####WARNING######
    If you decide to run this project, please ensure that you set the proper IO pins in config.h!!!

  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-07 12:24
    Bruce, I found that my code was overflowing the timer stack. I had only allocated 100 longs for the stack, and it was using 120 longs. This may be why it wasn't working for you. I've increase the timer stack to 200 longs, and it is working fine for me. I also changed the print that was coming from the WRITE routine so it now prints either H# or L#, where H and L represent high and low, and # is the pin number.

    Give this code a try and see if it works OK for you. If you type a command like "G1 X1" you should see prints showing the X pin toggling.
Sign In or Register to comment.