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

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

1235789

Comments

  • idbruceidbruce Posts: 6,197
    edited 2015-03-17 03:35
    In reference to my last, this was indeed an error, however if I had paid closer attention I would have noticed something very important. The original code looked like this:
    	if (DEBUG_DDA && (debug_flags & DEBUG_DDA))
        sersendf_P(PSTR("\nCreate: X %lq  Y %lq  Z %lq  F %lu\n"),
                   dda->endpoint.X, dda->endpoint.Y,
                   dda->endpoint.Z, dda->endpoint.F);
    
    	// we end at the passed target
    	memcpy(&(dda->endpoint), target, sizeof(TARGET));
    
    Source: Teacup Firmware


    Upon visiting the github archives, the code had been change to this:
      // We end at the passed target.
      memcpy(&(dda->endpoint), target, sizeof(TARGET));
    
    	if (DEBUG_DDA && (debug_flags & DEBUG_DDA))
        sersendf_P(PSTR("\nCreate: X %lq  Y %lq  Z %lq  F %lu\n"),
                   dda->endpoint.axis[X], dda->endpoint.axis[Y],
                   dda->endpoint.axis[Z], dda->endpoint.F);
    
    Source: Teacup Firmware

    During my troubleshooting, I failed to see that memcpy, but nonetheless, I found the error before going to github :)
  • idbruceidbruce Posts: 6,197
    edited 2015-03-17 06:36
    At this point, I can clearly see that I made a huge mistake by porting an old set of files. Before starting this port, I should have definitely downloaded the most recent files, because there have been some significant changes. Despite my resistance to starting over, after reviewing some of the changes that have been made to the Teacup Firmware, I am now inclined to believe that it is indeed in my best interest to start anew. Many wasted hours will be going down the drain, but I do not want to waste anymore time on a path that can only lead to further trouble.

    On the bright side, I am now fairly knowledgable about the firmware, and I now know what needs to be done to make it Propeller friendly. If I was not so picky about the indents and code appearance, I could probably knock it out in a day or two, but I like my code orderly for easy reading, so it will probably take me a week to get another good set of nice looking files.

    Considering the amount of work already lost and the amount of work that now needs to be done, I will be sticking to the same plan and program outline, as my previous attempt.

    Bruce

    EDIT: I have decided to start this fresh port by creating a small MFC dialog application to recursively go through all the files in a specified directory and remove all those little annoyances that I would normally have to manually edit. :) This should drastically cut down the fresh port time. :)

    EDIT: Referring to my last EDIT:, I should have done this a long time ago. This is going to ridiculously fast :)
  • idbruceidbruce Posts: 6,197
    edited 2015-03-17 09:10
    Dave

    With the updated files that you provided, I could not get it to allow input. And the previous files allowed input, but something was not right.

    Before you answer this question, please keep in mind, that when compiled out of the simulator, it will not fit the hub with LOOKAHEAD enabled. I still do not understand why the simulator would be beneficial to me. Before I get deep into my next round of porting, could you please try to explain the true benefit to this dense old soul?
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-17 10:14
    It worked fine on a C3 board that I tested it with. It should work on any board with a standard serial board. Note, the serial input is not echoed, so you won't see any feedback in the serial terminal until you hit the enter key.

    The usefullness of the simulator mode is that the original writer of the code took care of all the issue with simulating the AVR stuff. This helps to minimize the changes that need to be made to the code. There are a couple of advantages to minimizing code changes. It makes it easier to port code to another processor, and the changes are in a small number of files. This would allow you to send your code back to the original author, who might incorporate it in his master source.

    The only files that need to be modified are the ones in the simulator directory. You've already done work on interfacing to hardware on the Prop, and your changes could be incorporated in the driver files in the simulator directory.
  • D.PD.P Posts: 790
    edited 2015-03-17 14:46
    idbruce wrote: »
    At this point, I can clearly see that I made a huge mistake by porting an old set of files. Before starting this port, I should have definitely downloaded the most recent files, because there have been some significant changes. Despite my resistance to starting over, after reviewing some of the changes that have been made to the Teacup Firmware, I am now inclined to believe that it is indeed in my best interest to start anew. Many wasted hours will be going down the drain, but I do not want to waste anymore time on a path that can only lead to further trouble.

    On the bright side, I am now fairly knowledgable about the firmware, and I now know what needs to be done to make it Propeller friendly. If I was not so picky about the indents and code appearance, I could probably knock it out in a day or two, but I like my code orderly for easy reading, so it will probably take me a week to get another good set of nice looking files.

    Considering the amount of work already lost and the amount of work that now needs to be done, I will be sticking to the same plan and program outline, as my previous attempt.

    Bruce

    EDIT: I have decided to start this fresh port by creating a small MFC dialog application to recursively go through all the files in a specified directory and remove all those little annoyances that I would normally have to manually edit. :) This should drastically cut down the fresh port time. :)

    EDIT: Referring to my last EDIT:, I should have done this a long time ago. This is going to ridiculously fast :)

    http://rogerdudler.github.io/git-guide/

    Does take much effort, save you allot of pain.
  • edited 2015-03-17 15:32
    idbruce wrote: »
    Many wasted hours will be going down the drain, but I do not want to waste anymore time on a path that can only lead to further trouble.

    It's only a waste of time if you didn't learn anything. Usually, the second attempt will produce code that is half the size and twice as fast.

    Sandy
  • idbruceidbruce Posts: 6,197
    edited 2015-03-17 15:56
    Sandy
    It's only a waste of time if you didn't learn anything.

    Thanks Sandy, I needed to hear that.

    Bruce
  • idbruceidbruce Posts: 6,197
    edited 2015-03-18 06:45
    Dave
    The only files that need to be modified are the ones in the simulator directory. You've already done work on interfacing to hardware on the Prop, and your changes could be incorporated in the driver files in the simulator directory.

    Like I said, dense.

    I cannot visualize this working with cogs, clocks, interrupts, sd card reading, etc....

    Apparently you and Heater are seeing something that I am failing to see. I am not saying that is impossible, I just cannot see it happening.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-18 07:46
    But it does work. Just try running the code that I posted. The simulator can actually drive a 3D printer if it has a serial control interface.
    idbruce wrote: »
    I cannot visualize this working with cogs, clocks, interrupts, sd card reading, etc....
    From the C code cogs are just a special type of thread or interrupt. clocks are done by just reading the Prop CNT register, and using a cog if asynchronous clock operations need to be done. SD card reading can be done with the standard C driver, or you can write your own driver if you need to reduce the size of it.

    The challenge with the Prop is the 32K of RAM space. LMM won't fit, and CMM is very tight. Hopefully you can continue to use CMM. Otherwise you will need to use XMMC, which is quite slow.

    The code that I posted is single-threaded, and does not use an extra cog for the timer. This depends on the clock function to be called within the loops in the main code. If this is not fast enough you will have to put the timer code in its own cog, and then be very careful that there are no conflicts between the main code and the timer code. The Teacup code seems to have sufficient protection for this with the atomic waits.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-18 08:31
    Dave
    But it does work. Just try running the code that I posted. The simulator can actually drive a 3D printer if it has a serial control interface.

    As mentioned, I did try it.....

    I tried it with the first set of files, which allowed input and provided output. I tried it a second time with the patch files you provided, but this time, it neither allowed input or provided output.

    For the moment, I am going to continue on the path that I am on, but when I finish, I will make a serial interface for the simulator, and we will test.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-18 08:58
    Try typing "g1 x1" into the serial terminal. That works for me.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-18 10:10
    Dave

    I just did a bit more investigation on the simulator, and everything that I read indicates that it is just a simulator and is not intended to run a 3D printer.
    You can't (yet) run a stepper this way, but it's excellent to check accuracy of new algorithms.

    http://reprap.org/wiki/Teacup_Firmware#Running_Teacup_in_a_simulator
    http://reprap.org/wiki/SimulAVR
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-18 12:40
    I thought I posted a response to your post about an hour ago, but I don't see it. SimulAVR is an AVR simulator that run at non-realtime rates, so it wouldn't be usable for this application. The Teacup simulator mode can run on pretty much any machine. It logs the stepper pin settings to a file or a serial port, so it doesn't directly drive the stepper pins. You have to change simulator.c to drive the pins. simulator.c contains READ, WRITE, SET_INPUT and SET_OUTPUT routines that you would have to change to directly control the stepper pins.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-18 15:47
    In Post #121, I indicated that I had found an error in Teacup, and then in Post #122, I verified it.

    As I go through this next round of file editing, I have come across a couple other small errors, which I fixed. However, now I have come across something new, and I can only imagine that this code was once contained in a condition and the author had forgotten to remove the brackets. I cannot see any use for these brackets, but then again, I don't know everything :) So I pose the question.....

    In the code below, can you think of any useful purpose for the extra brackets or was this just an oversight on the authors part?
          case 119:
            //? --- M119: report endstop status ---
            //? Report the current status of the endstops configured in the
            //? firmware to the host.
            power_on();
            endstops_on();
            delay_ms(10); // allow the signal to stabilize
            {
              const char* const open = PSTR("open ");
              const char* const triggered = PSTR("triggered ");
    
              #if defined(X_MIN_PIN)
                sersendf_P(PSTR("x_min:"));
                x_min() ? sersendf_P(triggered) : sersendf_P(open);
              #endif
              #if defined(X_MAX_PIN)
                sersendf_P(PSTR("x_max:"));
                x_max() ? sersendf_P(triggered) : sersendf_P(open);
              #endif
              #if defined(Y_MIN_PIN)
                sersendf_P(PSTR("y_min:"));
                y_min() ? sersendf_P(triggered) : sersendf_P(open);
              #endif
              #if defined(Y_MAX_PIN)
                sersendf_P(PSTR("y_max:"));
                y_max() ? sersendf_P(triggered) : sersendf_P(open);
              #endif
              #if defined(Z_MIN_PIN)
                sersendf_P(PSTR("z_min:"));
                z_min() ? sersendf_P(triggered) : sersendf_P(open);
              #endif
              #if defined(Z_MAX_PIN)
                sersendf_P(PSTR("z_max:"));
                z_max() ? sersendf_P(triggered) : sersendf_P(open);
              #endif
              #if ! (defined(X_MIN_PIN) || defined(X_MAX_PIN) || \
                     defined(Y_MIN_PIN) || defined(Y_MAX_PIN) || \
                     defined(Z_MIN_PIN) || defined(Z_MAX_PIN))
                sersendf_P(PSTR("no endstops defined"));
              #endif
            }
            endstops_off();
            break;
    
    Source: Teacup Firmware
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-18 16:03
    The braces where probably added so that the variables open and triggered could be declared. There may also have been an if statement at some point, which was removed. I think with C99 the braces aren't needed to declare variables at the point, but I'm not very familiar with the C99 extensions.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-18 16:19
    The braces where probably added so that the variables open and triggered could be declared.

    hmmmmm....

    I will remove them from the old build and see if it compiles.

    Thanks Dave, I would not have thought of that one.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-18 16:28
    I would have to agree with your assumption, as compared to being in a condition, however it builds just fine with them commented out, so C99 probably does not require them. I forget how VS handled that.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 07:43
    That wasn't so horrible.

    I now have a new project with the most upto date Teacup files. However, it still has very similar problems as the last project and the comments still need to be better organized. Instead of going into the problems at this point, I will just say that it compiles, with three generated warnings, due to unused variables for currently commented portions of code.

    At this point, I do believe it is just a matter of troubleshooting some minor issues, and I think it will be ready to run correctly on the Propeller. However, the temperature and heating code still needs to be added.

    I will note two problems, next_move() is not being called correctly, and there is an AVR function that most likely needs an accurate definition, which would be pgm_read_dword. At the current time, I have it defined as follows:
    #define pgm_read_dword(x) (*((uint16_t *)(x)))
    

    Another note worth mentioning, it is still slightly too large to enable LOOKAHEAD.

    With the following configuration set in config.h:
      LOOKAHEAD disabled
      DEBUG enabled
      GCODE_SD enabled

    and with the debug flags now set in the main function as follows:
    	debug_flags |= DEBUG_STEP;
    	debug_flags |= DEBUG_DDA;
    	debug_flags |= DEBUG_POSITION;
    	debug_flags |= DEBUG_ECHO;
    

    and reading a GCODE file from the sd card, we now have terminal output, which indicates some of the remaining problems.


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


    Additionally, I am also including a different GCODE file for debugging purposes. This GCODE file only has G1 and M114 commands. I will use this particular file to nail down some of the remaining problems within this project.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 10:04
    next_move() is not being called correctly

    The condition if(isdead), within the enqueue_home function of dda_queue, is not being met, therefore the next_move function within dda_queue is not being called, and therefore, dda_start is not being called.

    I believe this is the biggest problem for finishing the port.
    	dda_create(new_movebuffer, t);
    
    	// make certain all writes to global memory
    	// are flushed before modifying mb_head.
    
    	//3/17/2015//Bruce//MEMORY_BARRIER();
    
    	mb_head = h;
    
    	uint8_t isdead;
    
    	//3/17/2015//Bruce//ATOMIC_START
     
    	isdead = (movebuffer[mb_tail].live == 0);
    
    	//3/17/2015//Bruce//ATOMIC_END
    
    	if(isdead)
    	{
    		next_move();
    
    		// Compensate for the cli() in setTimer().
    		//3/17/2015//Bruce//sei();
    	}
    
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 10:36
    Referring to my last post.......

    I have changed my mind, I now believe the problem is in step_timer.c. Just wanted to spit that out, before I leave :)
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-19 10:37
    It works in the simulator mode. So the question is why is "live" not being cleared to zero. There are only a few places where this happens. They are in dda.c and dda_queue.c. The most likely place is in dda_queue.c where waitfor_temp is set, and it is checking whether temp_achieved() is true. You might want to look in that area.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 14:07
    Dave
    The most likely place is in dda_queue.c where waitfor_temp is set, and it is checking whether temp_achieved() is true.

    While I was testing earlier, that was also my thought, but the code never reaches those points either. To help ensure and prevent such an occurance, I removed all codes except G1 and M114 codes from the sample code, so there are no codes that require temperature checks.

    If I try to place any debug statements within the step_timer, the terminal remains completely blue without any output. I am not sure how I can test that..
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 14:13
    Dave
    There are only a few places where this happens. They are in dda.c and dda_queue.c

    I believe dda_queue is where it all happens, but I also believe that most of the setting, clearing, and queue shifting occurs before it reaches dda_queue, my guess would be the dda or the step_timer.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 14:26
    With the exception of the two timers running in seperate cogs, this program is now being run in a single thread. I am almost beginning to think that the step timer could be eliminated, because set_timer is being called by the primary thread. I wish I had a much better understanding of interrupts and how it affected the original code.

    However since they do exist, I believe that functionality should be verified. If I am not mistaken, I think I verified the the clock timer this morning.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 14:34
    Furthermore, I have never seen an expression like this. Is this even legit?
    isdead = (movebuffer[mb_tail].live == 0);
    

    EDIT: An expression/condition LOL
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-19 14:45
    Yes, the statement is legit. It's just setting isdead to a logical value of either 0 or 1.

    I looked at your set_timer code. It has problems. You do waitcnt(next_step_time) with next_step_time equal to 0. This will wait until the counter wraps back around to 0, which will take around 50 seconds. Even if you change the value of next_step_time during that period, the waitcnt is waiting for 0. Once the counter hits zero you will call queue_step, and then reset next_step_time to 0, and then wait another 50+ seconds.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 14:52
    I just found a very important clue......

    clock_250ms is never being called from within time_clock.c, which would mean that the cog is not updating the counter properly
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-19 15:15
    It looks like you commented out all the ATOMIC_START/STOP. You are running with multiple cogs, and the ATOMIC stuff is needed. That could be killing things.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-19 15:43
    Dave
    It looks like you commented out all the ATOMIC_START/STOP. You are running with multiple cogs, and the ATOMIC stuff is needed. That could be killing things.
    With the exception of the two timers running in seperate cogs, this program is now being run in a single thread.

    The only possible code that those cogs should be able to affect is the setting of the clock flags, and that should be limited to the cog within timer.c. However I suppose it is highly possible.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-19 17:43
    If you are running the code like the original, then the main thread puts stuff on the queue, and one of the timer's will pull it off the queue. That requires atomic operations. The ATOMIC_START/STOP functions can be easily implemented on the Prop using lockset and lockclr.
Sign In or Register to comment.