-
Notifications
You must be signed in to change notification settings - Fork 0
/
Sprinter.pde
3589 lines (3124 loc) · 111 KB
/
Sprinter.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Reprap firmware based on Sprinter
Optimized for Sanguinololu 1.2 and above / RAMPS
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/*
This firmware is a mashup between Sprinter, grbl and parts from marlin.
(https://github.com/kliment/Sprinter)
Changes by Doppler Michael (midopple)
Planner is from Simen Svale Skogsrud
https://github.com/simen/grbl
Parts of Marlin Firmware from ErikZalm
https://github.com/ErikZalm/Marlin-non-gen6
Sprinter Changelog
- Look forward function --> calculate 16 Steps forward, get from Firmaware Marlin and Grbl
- Stepper control with Timer 1 (Interrupt)
- Extruder heating with PID use a Softpwm (Timer 2) with 500 hz to free Timer1 for Steppercontrol
- command M220 Sxxx --> tune Printing speed online (+/- 50 %)
- G2 / G3 command --> circle function
- Baudrate set to 250 kbaud
- Testet on Sanguinololu Board
- M30 Command can delete files on SD Card
- move string to flash to free RAM vor forward planner
- M203 Temperature monitor for Repetier
Version 1.3.04T
- Implement Plannercode from Marlin V1 big thanks to Erik
- Stepper interrupt with Step loops
- Stepperfrequency 30 Khz
- New Command
* M202 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec
* M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2
* M205 - advanced settings: minimum travel speed S=while printing T=travel only, X= maximum xy jerk, Z=maximum Z jerk, E = max E jerk
- Remove unused Variables
- Check Uart Puffer while circle processing (CMD: G2 / G3)
- Fast Xfer Function --> move Text to Flash
- Option to deactivate ARC (G2/G3) function (save flash)
- Removed modulo (%) operator, which uses an expensive divide
Version 1.3.05T
- changed homing function to not conflict with min_software_endstops/max_software_endstops (thanks rGlory)
- Changed check in arc_func
- Corrected distance calculation. (thanks jv4779)
- MAX Feed Rate for Z-Axis reduced to 2 mm/s some Printers had problems with 4 mm/s
Version 1.3.06T
- the microcontroller can store settings in the EEPROM
- M500 - stores paramters in EEPROM
- M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).
- M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
- M503 - Print settings
Version 1.3.07T
- Optimize Variable Size (faster Code)
- Remove unused Code from Interrupt --> faster ~ 22 us per step
- Replace abs with fabs --> Faster and smaler
- Add "store_eeprom.cpp" to makefile
Version 1.3.08T
- If a line starts with ';', it is ignored but comment_mode is reset.
A ';' inside a line ignores just the portion following the ';' character.
The beginning of the line is still interpreted.
- Same fix for SD Card, tested and work
Version 1.3.09T
- Move SLOWDOWN Function up
Version 1.3.10T
- Add info to GEN7 Pins
- Update pins.h for gen7, working setup for 20MHz
- calculate feedrate without extrude before planner block is set
- New Board --> GEN7 @ 20 Mhz …
- ENDSTOPS_ONLY_FOR_HOMING Option ignore Endstop always --> fault is cleared
Version 1.3.11T
- fix for broken include in store_eeprom.cpp --> Thanks to kmeehl (issue #145)
- Make fastio & Arduino pin numbering consistent for AT90USB128x. --> Thanks to lincomatic
- Select Speedtable with F_CPU
- Use same Values for Speedtables as Marlin
Version 1.3.12T
- Fixed arc offset.
Version 1.3.13T
- Extrudemultiply with code M221 Sxxx (S100 original Extrude value)
- use Feedratefactor only when Extrude > 0
- M106 / M107 can drive the FAN with PWM + Port check for not using Timer 1
- Added M93 command. Sends current steps for all axis.
- New Option --> FAN_SOFT_PWM, with this option the FAN PWM can use every digital I/O
Version 1.3.14T
- When endstop is hit count the virtual steps, so the print lose no position when endstop is hit
Version 1.3.15T
- M206 - set additional homing offset
- Option for minimum FAN start speed --> #define MINIMUM_FAN_START_SPEED 50 (set it to zero to deactivate)
Version 1.3.16T
- Extra Max Feedrate for Retract (MAX_RETRACT_FEEDRATE)
Version 1.3.17T
- M303 - PID relay autotune possible
- G4 Wait until last move is done
Version 1.3.18T
- Problem with Thermistor 3 table when sensor is broken and temp is -20 °C
Version 1.3.19T
- Set maximum acceleration. If "steps per unit" is Change the acc were not recalculated
- Extra Parameter for Max Extruder Jerk
- New Parameter (max_e_jerk) in EEPROM --> Default settings after update !
Version 1.3.20T
- fix a few typos and correct english usage
- reimplement homing routine as an inline function
- refactor eeprom routines to make it possible to modify the value of a single parameter
- calculate eeprom parameter addresses based on previous param address plus sizeof(type)
- add 0 C point in Thermistortable 7
Version 1.3.21T
- M301 set PID Parameter, and Store to EEPROM
- If no PID is used, deaktivate Variables for PID settings
Version 1.3.22T
- Error in JERK calculation after G92 command is send, make problems
with Z-Lift function in Slic3r
- Add homing values can shown with M206 D
*/
#include <avr/pgmspace.h>
#include <math.h>
#include "fastio.h"
#include "Configuration.h"
#include "pins.h"
#include "Sprinter.h"
#include "speed_lookuptable.h"
#include "heater.h"
#ifdef USE_ARC_FUNCTION
#include "arc_func.h"
#endif
#ifdef SDSUPPORT
#include "SdFat.h"
#endif
#ifdef USE_EEPROM_SETTINGS
#include "store_eeprom.h"
#endif
#ifndef CRITICAL_SECTION_START
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli()
#define CRITICAL_SECTION_END SREG = _sreg
#endif //CRITICAL_SECTION_START
void __cxa_pure_virtual(){};
// look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html
// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
//Implemented Codes
//-------------------
// G0 -> G1
// G1 - Coordinated Movement X Y Z E
// G2 - CW ARC
// G3 - CCW ARC
// G4 - Dwell S<seconds> or P<milliseconds>
// G28 - Home all Axis
// G90 - Use Absolute Coordinates
// G91 - Use Relative Coordinates
// G92 - Set current position to cordinates given
//RepRap M Codes
// M104 - Set extruder target temp
// M105 - Read current temp
// M106 - Fan on
// M107 - Fan off
// M109 - Wait for extruder current temp to reach target temp.
// M114 - Display current position
//Custom M Codes
// M20 - List SD card
// M21 - Init SD card
// M22 - Release SD card
// M23 - Select SD file (M23 filename.g)
// M24 - Start/resume SD print
// M25 - Pause SD print
// M26 - Set SD position in bytes (M26 S12345)
// M27 - Report SD print status
// M28 - Start SD write (M28 filename.g)
// M29 - Stop SD write
// - <filename> - Delete file on sd card
// M42 - Set output on free pins, on a non pwm pin (over pin 13 on an arduino mega) use S255 to turn it on and S0 to turn it off. Use P to decide the pin (M42 P23 S255) would turn pin 23 on
// M80 - Turn on Power Supply
// M81 - Turn off Power Supply
// M82 - Set E codes absolute (default)
// M83 - Set E codes relative while in Absolute Coordinates (G90) mode
// M84 - Disable steppers until next move,
// or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout.
// M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
// M92 - Set axis_steps_per_unit - same syntax as G92
// M93 - Send axis_steps_per_unit
// M115 - Capabilities string
// M119 - Show Endstopper State
// M140 - Set bed target temp
// M190 - Wait for bed current temp to reach target temp.
// M201 - Set maximum acceleration in units/s^2 for print moves (M201 X1000 Y1000)
// M202 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec
// M203 - Set temperture monitor to Sx
// M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) in mm/sec^2
// M205 - advanced settings: minimum travel speed S=while printing T=travel only, X=maximum xy jerk, Z=maximum Z jerk
// M206 - set additional homing offset
// M220 - set speed factor override percentage S=factor in percent
// M221 - set extruder multiply factor S100 --> original Extrude Speed
// M301 - Set PID parameters P I and D
// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
// M400 - Finish all moves
// M500 - stores paramters in EEPROM
// M501 - reads parameters from EEPROM (if you need to reset them after you changed them temporarily).
// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
// M503 - Print settings
// Debug feature / Testing the PID for Hotend
// M601 - Show Temp jitter from Extruder (min / max value from Hotend Temperature while printing)
// M602 - Reset Temp jitter from Extruder (min / max val) --> Don't use it while Printing
// M603 - Show Free Ram
#define _VERSION_TEXT "1.3.22T / 20.08.2012"
//Stepper Movement Variables
char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
float axis_steps_per_unit[4] = _AXIS_STEP_PER_UNIT;
float max_feedrate[4] = _MAX_FEEDRATE;
float homing_feedrate[] = _HOMING_FEEDRATE;
bool axis_relative_modes[] = _AXIS_RELATIVE_MODES;
float move_acceleration = _ACCELERATION; // Normal acceleration mm/s^2
float retract_acceleration = _RETRACT_ACCELERATION; // Normal acceleration mm/s^2
float max_xy_jerk = _MAX_XY_JERK;
float max_z_jerk = _MAX_Z_JERK;
float max_e_jerk = _MAX_E_JERK;
unsigned long min_seg_time = _MIN_SEG_TIME;
#ifdef PIDTEMP
unsigned int PID_Kp = PID_PGAIN, PID_Ki = PID_IGAIN, PID_Kd = PID_DGAIN;
#endif
long max_acceleration_units_per_sq_second[4] = _MAX_ACCELERATION_UNITS_PER_SQ_SECOND; // X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts
//float max_start_speed_units_per_second[] = _MAX_START_SPEED_UNITS_PER_SECOND;
//long max_travel_acceleration_units_per_sq_second[] = _MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND; // X, Y, Z max acceleration in mm/s^2 for travel moves
float mintravelfeedrate = DEFAULT_MINTRAVELFEEDRATE;
float minimumfeedrate = DEFAULT_MINIMUMFEEDRATE;
unsigned long axis_steps_per_sqr_second[NUM_AXIS];
unsigned long plateau_steps;
//unsigned long axis_max_interval[NUM_AXIS];
//unsigned long axis_travel_steps_per_sqr_second[NUM_AXIS];
//unsigned long max_interval;
//unsigned long steps_per_sqr_second;
//adjustable feed factor for online tuning printer speed
volatile int feedmultiply=100; //100->original / 200 -> Factor 2 / 50 -> Factor 0.5
int saved_feedmultiply;
volatile bool feedmultiplychanged=false;
volatile int extrudemultiply=100; //100->1 200->2
//boolean acceleration_enabled = false, accelerating = false;
//unsigned long interval;
float destination[NUM_AXIS] = {0.0, 0.0, 0.0, 0.0};
float current_position[NUM_AXIS] = {0.0, 0.0, 0.0, 0.0};
float add_homing[3]={0,0,0};
static unsigned short virtual_steps_x = 0;
static unsigned short virtual_steps_y = 0;
static unsigned short virtual_steps_z = 0;
bool home_all_axis = true;
//unsigned ?? ToDo: Check
int feedrate = 1500, next_feedrate, saved_feedrate;
long gcode_N, gcode_LastN;
bool relative_mode = false; //Determines Absolute or Relative Coordinates
//unsigned long steps_taken[NUM_AXIS];
//long axis_interval[NUM_AXIS]; // for speed delay
//float time_for_move;
//bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode.
//long timediff = 0;
bool is_homing = false;
//experimental feedrate calc
//float d = 0;
//float axis_diff[NUM_AXIS] = {0, 0, 0, 0};
#ifdef USE_ARC_FUNCTION
//For arc center point coordinates, sent by commands G2/G3
float offset[3] = {0.0, 0.0, 0.0};
#endif
#ifdef STEP_DELAY_RATIO
long long_step_delay_ratio = STEP_DELAY_RATIO * 100;
#endif
///oscillation reduction
#ifdef RAPID_OSCILLATION_REDUCTION
float cumm_wait_time_in_dir[NUM_AXIS]={0.0,0.0,0.0,0.0};
bool prev_move_direction[NUM_AXIS]={1,1,1,1};
float osc_wait_remainder = 0.0;
#endif
#if (MINIMUM_FAN_START_SPEED > 0)
unsigned char fan_last_speed = 0;
unsigned char fan_org_start_speed = 0;
unsigned long previous_millis_fan_start = 0;
#endif
// comm variables and Commandbuffer
// BUFSIZE is reduced from 8 to 6 to free more RAM for the PLANNER
#define MAX_CMD_SIZE 96
#define BUFSIZE 6 //8
char cmdbuffer[BUFSIZE][MAX_CMD_SIZE];
bool fromsd[BUFSIZE];
//Need 1kb Ram --> only work with Atmega1284
#ifdef SD_FAST_XFER_AKTIV
char fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE + 1];
int lastxferchar;
long xferbytes;
#endif
unsigned char bufindr = 0;
unsigned char bufindw = 0;
unsigned char buflen = 0;
char serial_char;
int serial_count = 0;
boolean comment_mode = false;
char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc
//Send Temperature in °C to Host
int hotendtC = 0, bedtempC = 0;
//Inactivity shutdown variables
unsigned long previous_millis_cmd = 0;
unsigned long max_inactive_time = 0;
unsigned long stepper_inactive_time = 0;
//Temp Monitor for repetier
unsigned char manage_monitor = 255;
//------------------------------------------------
//Init the SD card
//------------------------------------------------
#ifdef SDSUPPORT
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
uint32_t filesize = 0;
uint32_t sdpos = 0;
bool sdmode = false;
bool sdactive = false;
bool savetosd = false;
int16_t read_char_int;
void initsd()
{
sdactive = false;
#if SDSS >- 1
if(root.isOpen())
root.close();
if (!card.init(SPI_FULL_SPEED,SDSS)){
//if (!card.init(SPI_HALF_SPEED,SDSS))
showString(PSTR("SD init fail\r\n"));
}
else if (!volume.init(&card))
showString(PSTR("volume.init failed\r\n"));
else if (!root.openRoot(&volume))
showString(PSTR("openRoot failed\r\n"));
else{
sdactive = true;
print_disk_info();
#ifdef SDINITFILE
file.close();
if(file.open(&root, "init.g", O_READ)){
sdpos = 0;
filesize = file.fileSize();
sdmode = true;
}
#endif
}
#endif
}
#ifdef SD_FAST_XFER_AKTIV
#ifdef PIDTEMP
extern volatile unsigned char g_heater_pwm_val;
#endif
void fast_xfer()
{
char *pstr;
boolean done = false;
//force heater pins low
if(HEATER_0_PIN > -1) WRITE(HEATER_0_PIN,LOW);
if(HEATER_1_PIN > -1) WRITE(HEATER_1_PIN,LOW);
#ifdef PIDTEMP
g_heater_pwm_val = 0;
#endif
lastxferchar = 1;
xferbytes = 0;
pstr = strstr(strchr_pointer+4, " ");
if(pstr == NULL)
{
showString(PSTR("invalid command\r\n"));
return;
}
*pstr = '\0';
//check mode (currently only RAW is supported
if(strcmp(strchr_pointer+4, "RAW") != 0)
{
showString(PSTR("Invalid transfer codec\r\n"));
return;
}else{
showString(PSTR("Selected codec: "));
Serial.println(strchr_pointer+4);
}
if (!file.open(&root, pstr+1, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
{
showString(PSTR("open failed, File: "));
Serial.print(pstr+1);
showString(PSTR("."));
}else{
showString(PSTR("Writing to file: "));
Serial.println(pstr+1);
}
showString(PSTR("ok\r\n"));
//RAW transfer codec
//Host sends \0 then up to SD_FAST_XFER_CHUNK_SIZE then \0
//when host is done, it sends \0\0.
//if a non \0 character is recieved at the beginning, host has failed somehow, kill the transfer.
//read SD_FAST_XFER_CHUNK_SIZE bytes (or until \0 is recieved)
while(!done)
{
while(!Serial.available())
{
}
if(Serial.read() != 0)
{
//host has failed, this isn't a RAW chunk, it's an actual command
file.sync();
file.close();
return;
}
for(int i=0;i<SD_FAST_XFER_CHUNK_SIZE+1;i++)
{
while(!Serial.available())
{
}
lastxferchar = Serial.read();
//buffer the data...
fastxferbuffer[i] = lastxferchar;
xferbytes++;
if(lastxferchar == 0)
break;
}
if(fastxferbuffer[0] != 0)
{
fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE] = 0;
file.write(fastxferbuffer);
showString(PSTR("ok\r\n"));
}else{
showString(PSTR("Wrote "));
Serial.print(xferbytes);
showString(PSTR(" bytes.\r\n"));
done = true;
}
}
file.sync();
file.close();
}
#endif
void print_disk_info(void)
{
// print the type of card
showString(PSTR("\nCard type: "));
switch(card.type())
{
case SD_CARD_TYPE_SD1:
showString(PSTR("SD1\r\n"));
break;
case SD_CARD_TYPE_SD2:
showString(PSTR("SD2\r\n"));
break;
case SD_CARD_TYPE_SDHC:
showString(PSTR("SDHC\r\n"));
break;
default:
showString(PSTR("Unknown\r\n"));
}
//uint64_t freeSpace = volume.clusterCount()*volume.blocksPerCluster()*512;
//uint64_t occupiedSpace = (card.cardSize()*512) - freeSpace;
// print the type and size of the first FAT-type volume
uint32_t volumesize;
showString(PSTR("\nVolume type is FAT"));
Serial.println(volume.fatType(), DEC);
volumesize = volume.blocksPerCluster(); // clusters are collections of blocks
volumesize *= volume.clusterCount(); // we'll have a lot of clusters
volumesize *= 512; // SD card blocks are always 512 bytes
volumesize /= 1024; //kbytes
volumesize /= 1024; //Mbytes
showString(PSTR("Volume size (Mbytes): "));
Serial.println(volumesize);
// list all files in the card with date and size
//root.ls(LS_R | LS_DATE | LS_SIZE);
}
FORCE_INLINE void write_command(char *buf)
{
char* begin = buf;
char* npos = 0;
char* end = buf + strlen(buf) - 1;
file.writeError = false;
if((npos = strchr(buf, 'N')) != NULL)
{
begin = strchr(npos, ' ') + 1;
end = strchr(npos, '*') - 1;
}
end[1] = '\r';
end[2] = '\n';
end[3] = '\0';
//Serial.println(begin);
file.write(begin);
if (file.writeError)
{
showString(PSTR("error writing to file\r\n"));
}
}
#endif
int FreeRam1(void)
{
extern int __bss_end;
extern int* __brkval;
int free_memory;
if (reinterpret_cast<int>(__brkval) == 0)
{
// if no heap use from end of bss section
free_memory = reinterpret_cast<int>(&free_memory) - reinterpret_cast<int>(&__bss_end);
}
else
{
// use from top of stack to heap
free_memory = reinterpret_cast<int>(&free_memory) - reinterpret_cast<int>(__brkval);
}
return free_memory;
}
//------------------------------------------------
//Function the check the Analog OUT pin for not using the Timer1
//------------------------------------------------
void analogWrite_check(uint8_t check_pin, int val)
{
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
//Atmega168/328 can't use OCR1A and OCR1B
//These are pins PB1/PB2 or on Arduino D9/D10
if((check_pin != 9) && (check_pin != 10))
{
analogWrite(check_pin, val);
}
#endif
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
//Atmega664P/1284P can't use OCR1A and OCR1B
//These are pins PD4/PD5 or on Arduino D12/D13
if((check_pin != 12) && (check_pin != 13))
{
analogWrite(check_pin, val);
}
#endif
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//Atmega1280/2560 can't use OCR1A, OCR1B and OCR1C
//These are pins PB5,PB6,PB7 or on Arduino D11,D12 and D13
if((check_pin != 11) && (check_pin != 12) && (check_pin != 13))
{
analogWrite(check_pin, val);
}
#endif
}
//------------------------------------------------
//Print a String from Flash to Serial (save RAM)
//------------------------------------------------
void showString (PGM_P s)
{
char c;
while ((c = pgm_read_byte(s++)) != 0)
Serial.print(c);
}
//------------------------------------------------
// Init
//------------------------------------------------
void setup()
{
Serial.begin(BAUDRATE);
showString(PSTR("Sprinter\r\n"));
showString(PSTR(_VERSION_TEXT));
showString(PSTR("\r\n"));
showString(PSTR("start\r\n"));
for(int i = 0; i < BUFSIZE; i++)
{
fromsd[i] = false;
}
//Initialize Dir Pins
#if X_DIR_PIN > -1
SET_OUTPUT(X_DIR_PIN);
#endif
#if Y_DIR_PIN > -1
SET_OUTPUT(Y_DIR_PIN);
#endif
#if Z_DIR_PIN > -1
SET_OUTPUT(Z_DIR_PIN);
#endif
#if E_DIR_PIN > -1
SET_OUTPUT(E_DIR_PIN);
#endif
//Initialize Enable Pins - steppers default to disabled.
#if (X_ENABLE_PIN > -1)
SET_OUTPUT(X_ENABLE_PIN);
if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH);
#endif
#if (Y_ENABLE_PIN > -1)
SET_OUTPUT(Y_ENABLE_PIN);
if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);
#endif
#if (Z_ENABLE_PIN > -1)
SET_OUTPUT(Z_ENABLE_PIN);
if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH);
#endif
#if (E_ENABLE_PIN > -1)
SET_OUTPUT(E_ENABLE_PIN);
if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH);
#endif
#ifdef CONTROLLERFAN_PIN
SET_OUTPUT(CONTROLLERFAN_PIN); //Set pin used for driver cooling fan
#endif
#ifdef EXTRUDERFAN_PIN
SET_OUTPUT(EXTRUDERFAN_PIN); //Set pin used for extruder cooling fan
#endif
//endstops and pullups
#ifdef ENDSTOPPULLUPS
#if X_MIN_PIN > -1
SET_INPUT(X_MIN_PIN);
WRITE(X_MIN_PIN,HIGH);
#endif
#if X_MAX_PIN > -1
SET_INPUT(X_MAX_PIN);
WRITE(X_MAX_PIN,HIGH);
#endif
#if Y_MIN_PIN > -1
SET_INPUT(Y_MIN_PIN);
WRITE(Y_MIN_PIN,HIGH);
#endif
#if Y_MAX_PIN > -1
SET_INPUT(Y_MAX_PIN);
WRITE(Y_MAX_PIN,HIGH);
#endif
#if Z_MIN_PIN > -1
SET_INPUT(Z_MIN_PIN);
WRITE(Z_MIN_PIN,HIGH);
#endif
#if Z_MAX_PIN > -1
SET_INPUT(Z_MAX_PIN);
WRITE(Z_MAX_PIN,HIGH);
#endif
#else
#if X_MIN_PIN > -1
SET_INPUT(X_MIN_PIN);
#endif
#if X_MAX_PIN > -1
SET_INPUT(X_MAX_PIN);
#endif
#if Y_MIN_PIN > -1
SET_INPUT(Y_MIN_PIN);
#endif
#if Y_MAX_PIN > -1
SET_INPUT(Y_MAX_PIN);
#endif
#if Z_MIN_PIN > -1
SET_INPUT(Z_MIN_PIN);
#endif
#if Z_MAX_PIN > -1
SET_INPUT(Z_MAX_PIN);
#endif
#endif
#if (HEATER_0_PIN > -1)
SET_OUTPUT(HEATER_0_PIN);
WRITE(HEATER_0_PIN,LOW);
#endif
#if (HEATER_1_PIN > -1)
SET_OUTPUT(HEATER_1_PIN);
WRITE(HEATER_1_PIN,LOW);
#endif
//Initialize Fan Pin
#if (FAN_PIN > -1)
SET_OUTPUT(FAN_PIN);
#endif
//Initialize Alarm Pin
#if (ALARM_PIN > -1)
SET_OUTPUT(ALARM_PIN);
WRITE(ALARM_PIN,LOW);
#endif
//Initialize LED Pin
#if (LED_PIN > -1)
SET_OUTPUT(LED_PIN);
WRITE(LED_PIN,LOW);
#endif
//Initialize Step Pins
#if (X_STEP_PIN > -1)
SET_OUTPUT(X_STEP_PIN);
#endif
#if (Y_STEP_PIN > -1)
SET_OUTPUT(Y_STEP_PIN);
#endif
#if (Z_STEP_PIN > -1)
SET_OUTPUT(Z_STEP_PIN);
#endif
#if (E_STEP_PIN > -1)
SET_OUTPUT(E_STEP_PIN);
#endif
// for(int i=0; i < NUM_AXIS; i++){
// axis_max_interval[i] = 100000000.0 / (max_start_speed_units_per_second[i] * axis_steps_per_unit[i]);
// axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
// axis_travel_steps_per_sqr_second[i] = max_travel_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
// }
#ifdef HEATER_USES_MAX6675
SET_OUTPUT(SCK_PIN);
WRITE(SCK_PIN,0);
SET_OUTPUT(MOSI_PIN);
WRITE(MOSI_PIN,1);
SET_INPUT(MISO_PIN);
WRITE(MISO_PIN,1);
SET_OUTPUT(MAX6675_SS);
WRITE(MAX6675_SS,1);
#endif
#ifdef SDSUPPORT
//power to SD reader
#if SDPOWER > -1
SET_OUTPUT(SDPOWER);
WRITE(SDPOWER,HIGH);
#endif
showString(PSTR("SD Start\r\n"));
initsd();
#endif
#if defined(PID_SOFT_PWM) || (defined(FAN_SOFT_PWM) && (FAN_PIN > -1))
showString(PSTR("Soft PWM Init\r\n"));
init_Timer2_softpwm();
#endif
showString(PSTR("Planner Init\r\n"));
plan_init(); // Initialize planner;
showString(PSTR("Stepper Timer init\r\n"));
st_init(); // Initialize stepper
#ifdef USE_EEPROM_SETTINGS
//first Value --> Init with default
//second value --> Print settings to UART
EEPROM_RetrieveSettings(false,false);
#endif
#ifdef PIDTEMP
updatePID();
#endif
//Free Ram
showString(PSTR("Free Ram: "));
Serial.println(FreeRam1());
//Planner Buffer Size
showString(PSTR("Plan Buffer Size:"));
Serial.print((int)sizeof(block_t)*BLOCK_BUFFER_SIZE);
showString(PSTR(" / "));
Serial.println(BLOCK_BUFFER_SIZE);
for(int8_t i=0; i < NUM_AXIS; i++)
{
axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
}
}
//------------------------------------------------
//MAIN LOOP
//------------------------------------------------
void loop()
{
if(buflen < (BUFSIZE-1))
get_command();
if(buflen)
{
#ifdef SDSUPPORT
if(savetosd)
{
if(strstr(cmdbuffer[bufindr],"M29") == NULL)
{
write_command(cmdbuffer[bufindr]);
showString(PSTR("ok\r\n"));
}
else
{
file.sync();
file.close();
savetosd = false;
showString(PSTR("Done saving file.\r\n"));
}
}
else
{
process_commands();
}
#else
process_commands();
#endif
buflen = (buflen-1);
//bufindr = (bufindr + 1)%BUFSIZE;
//Removed modulo (%) operator, which uses an expensive divide and multiplication
bufindr++;
if(bufindr == BUFSIZE) bufindr = 0;
}
//check heater every n milliseconds
manage_heater();
manage_inactivity(1);
#if (MINIMUM_FAN_START_SPEED > 0)
manage_fan_start_speed();
#endif
}
//------------------------------------------------
//Check Uart buffer while arc function ist calc a circle
//------------------------------------------------
void check_buffer_while_arc()
{
if(buflen < (BUFSIZE-1))
{
get_command();
}
}
//------------------------------------------------
//READ COMMAND FROM UART
//------------------------------------------------
void get_command()
{
while( Serial.available() > 0 && buflen < BUFSIZE)
{
serial_char = Serial.read();
if(serial_char == '\n' || serial_char == '\r' || (serial_char == ':' && comment_mode == false) || serial_count >= (MAX_CMD_SIZE - 1) )
{
if(!serial_count) { //if empty line
comment_mode = false; // for new command
return;
}
cmdbuffer[bufindw][serial_count] = 0; //terminate string
fromsd[bufindw] = false;
if(strstr(cmdbuffer[bufindw], "N") != NULL)
{
strchr_pointer = strchr(cmdbuffer[bufindw], 'N');
gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10));
if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) )
{
showString(PSTR("Serial Error: Line Number is not Last Line Number+1, Last Line:"));
Serial.println(gcode_LastN);
//Serial.println(gcode_N);
FlushSerialRequestResend();
serial_count = 0;
return;
}
if(strstr(cmdbuffer[bufindw], "*") != NULL)
{
byte checksum = 0;
byte count = 0;
while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++];
strchr_pointer = strchr(cmdbuffer[bufindw], '*');
if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum)
{
showString(PSTR("Error: checksum mismatch, Last Line:"));
Serial.println(gcode_LastN);
FlushSerialRequestResend();
serial_count = 0;