Пример #1
0
void error_detect_sensor_disconnected(int deviceReading, struct ErrorCounter* errCounter, char* deviceName) {
	//Check if the last 6 counts has been the same (= something is wrong)
	if (deviceReading == 1023) {
		errCounter->counter++;
		//errCounter->lastValue = deviceReading;
	} else {
		//errCounter->lastValue = deviceReading;
		errCounter->counter = 0;
	}

	if (errCounter->counter == 6) {
		emergency_stop(deviceName,"Disconnected");
	}
}
Пример #2
0
/* ENQUEUES detected candy to bouded-buffer  */
int buffer_enqueue(struct BoundedBuffer* bb, struct Candy candy) {

	/* If the write pointer, plus one, equals the read pointer,
	 * then the buffer is full. */
	if(((bb->write + 1) % bb->size) == bb->read)
		emergency_stop("Buffer full:",bb->prettyname);//instead of return -1;

	/* Buffer is initialized to contain a finit amount of candy.
	 * Therefore, we alter the value of the current candy pointed
	 * to by the write-head of the buffer. */
	bb->buffer[bb->write] = candy;

	/* Make the buffer circular */
	bb->write= (bb->write + 1) % bb->size;

	return 0;
}
Пример #3
0
void error_detect_is_dog_alive() {
	if(systick_get_ms() - lastDogKickReceived > 200) { // > X, where X is the time in ms. that we allow the NXTs to NOT communicate.
		emergency_stop("RS485 Error","Watchdog Timeout");
	}
}
Пример #4
0
void process_gcode_command() {
	uint32_t	backup_f;

	// convert relative to absolute
	if (next_target.option_all_relative) {
		next_target.target.X += startpoint.X;
		next_target.target.Y += startpoint.Y;
		next_target.target.Z += startpoint.Z;
	}

	// E relative movement.
	// Matches Sprinter's behaviour as of March 2012.
	if (next_target.option_all_relative || next_target.option_e_relative)
		next_target.target.e_relative = 1;
	else
		next_target.target.e_relative = 0;

	// implement axis limits
	#ifdef	X_MIN
		if (next_target.target.X < X_MIN * 1000.)
			next_target.target.X = X_MIN * 1000.;
	#endif
	#ifdef	X_MAX
		if (next_target.target.X > X_MAX * 1000.)
			next_target.target.X = X_MAX * 1000.;
	#endif
	#ifdef	Y_MIN
		if (next_target.target.Y < Y_MIN * 1000.)
			next_target.target.Y = Y_MIN * 1000.;
	#endif
	#ifdef	Y_MAX
		if (next_target.target.Y > Y_MAX * 1000.)
			next_target.target.Y = Y_MAX * 1000.;
	#endif
	#ifdef	Z_MIN
		if (next_target.target.Z < Z_MIN * 1000.)
			next_target.target.Z = Z_MIN * 1000.;
	#endif
	#ifdef	Z_MAX
		if (next_target.target.Z > Z_MAX * 1000.)
			next_target.target.Z = Z_MAX * 1000.;
	#endif


	// The GCode documentation was taken from http://reprap.org/wiki/Gcode .

	if (next_target.seen_T) {
	    //? --- T: Select Tool ---
	    //?
	    //? Example: T1
	    //?
	    //? Select extruder number 1 to build with.  Extruder numbering starts at 0.

	    next_tool = next_target.T;
	}

	if (next_target.seen_G) {
		uint8_t axisSelected = 0;
		switch (next_target.G) {
			case 0:
				//? G0: Rapid Linear Motion
				//?
				//? Example: G0 X12
				//?
				//? In this case move rapidly to X = 12 mm.  In fact, the RepRap firmware uses exactly the same code for rapid as it uses for controlled moves (see G1 below), as - for the RepRap machine - this is just as efficient as not doing so.  (The distinction comes from some old machine tools that used to move faster if the axes were not driven in a straight line.  For them G0 allowed any movement in space to get to the destination as fast as possible.)
				//?
				backup_f = next_target.target.F;
				next_target.target.F = MAXIMUM_FEEDRATE_X * 2L;
				enqueue(&next_target.target);
				next_target.target.F = backup_f;
				break;

			case 1:
				//? --- G1: Linear Motion at Feed Rate ---
				//?
				//? Example: G1 X90.6 Y13.8 E22.4
				//?
				//? Go in a straight line from the current (X, Y) point to the point (90.6, 13.8), extruding material as the move happens from the current extruded length to a length of 22.4 mm.
				//?
				enqueue(&next_target.target);
				break;

				//	G2 - Arc Clockwise
				// unimplemented

				//	G3 - Arc Counter-clockwise
				// unimplemented

			case 4:
				//? --- G4: Dwell ---
				//?
				//? Example: G4 P200
				//?
				//? In this case sit still doing nothing for 200 milliseconds.  During delays the state of the machine (for example the temperatures of its extruders) will still be preserved and controlled.
				//?
				queue_wait();
				// delay
				if (next_target.seen_P) {
					for (;next_target.P > 0;next_target.P--) {
						clock();
						delay_ms(1);
					}
				}
				break;

			case 20:
				//? --- G20: Set Units to Inches ---
				//?
				//? Example: G20
				//?
				//? Units from now on are in inches.
				//?
				next_target.option_inches = 1;
				break;

			case 21:
				//? --- G21: Set Units to Millimeters ---
				//?
				//? Example: G21
				//?
				//? Units from now on are in millimeters.  (This is the RepRap default.)
				//?
				next_target.option_inches = 0;
				break;

			case 30:
				//? --- G30: Go home via point ---
				//?
				//? Undocumented.
				enqueue(&next_target.target);
				// no break here, G30 is move and then go home

			case 28:
				//? --- G28: Home ---
				//?
				//? Example: G28
				//?
				//? This causes the RepRap machine to move back to its X, Y and Z zero endstops.  It does so accelerating, so as to get there fast.  But when it arrives it backs off by 1 mm in each direction slowly, then moves back slowly to the stop.  This ensures more accurate positioning.
				//?
				//? If you add coordinates, then just the axes with coordinates specified will be zeroed.  Thus
				//?
				//? G28 X0 Y72.3
				//?
				//? will zero the X and Y axes, but not Z.  The actual coordinate values are ignored.
				//?

				queue_wait();

				if (next_target.seen_X) {
					#if defined	X_MIN_PIN
						home_x_negative();
					#elif defined X_MAX_PIN
						home_x_positive();
					#endif
					axisSelected = 1;
				}
				if (next_target.seen_Y) {
					#if defined	Y_MIN_PIN
						home_y_negative();
					#elif defined Y_MAX_PIN
						home_y_positive();
					#endif
					axisSelected = 1;
				}
				if (next_target.seen_Z) {
					#if defined Z_MAX_PIN
						home_z_positive();
					#elif defined	Z_MIN_PIN
						home_z_negative();
					#endif
					axisSelected = 1;
				}
				// there's no point in moving E, as E has no endstops

				if (!axisSelected) {
					home();
				}
				break;

			case 90:
				//? --- G90: Set to Absolute Positioning ---
				//?
				//? Example: G90
				//?
				//? All coordinates from now on are absolute relative to the origin
				//? of the machine. This is the RepRap default.
				//?
				//? If you ever want to switch back and forth between relative and
				//? absolute movement keep in mind, X, Y and Z follow the machine's
				//? coordinate system while E doesn't change it's position in the
				//? coordinate system on relative movements.
				//?

				// No wait_queue() needed.
				next_target.option_all_relative = 0;
				break;

			case 91:
				//? --- G91: Set to Relative Positioning ---
				//?
				//? Example: G91
				//?
				//? All coordinates from now on are relative to the last position.
				//?

				// No wait_queue() needed.
				next_target.option_all_relative = 1;
				break;

			case 92:
				//? --- G92: Set Position ---
				//?
				//? Example: G92 X10 E90
				//?
				//? Allows programming of absolute zero point, by reseting the current position to the values specified.  This would set the machine's X coordinate to 10, and the extrude coordinate to 90. No physical motion will occur.
				//?

				queue_wait();

				if (next_target.seen_X) {
					startpoint.X = next_target.target.X;
					axisSelected = 1;
				}
				if (next_target.seen_Y) {
					startpoint.Y = next_target.target.Y;
					axisSelected = 1;
				}
				if (next_target.seen_Z) {
					startpoint.Z = next_target.target.Z;
					axisSelected = 1;
				}
				if (next_target.seen_E) {
					startpoint.E = next_target.target.E;
					axisSelected = 1;
				}

				if (axisSelected == 0) {
					startpoint.X = next_target.target.X =
					startpoint.Y = next_target.target.Y =
					startpoint.Z = next_target.target.Z =
					startpoint.E = next_target.target.E = 0;
				}

				dda_new_startpoint();
				break;

			case 161:
				//? --- G161: Home negative ---
				//?
				//? Find the minimum limit of the specified axes by searching for the limit switch.
				//?
				if (next_target.seen_X)
					home_x_negative();
				if (next_target.seen_Y)
					home_y_negative();
				if (next_target.seen_Z)
					home_z_negative();
				break;

			case 162:
				//? --- G162: Home positive ---
				//?
				//? Find the maximum limit of the specified axes by searching for the limit switch.
				//?
				if (next_target.seen_X)
					home_x_positive();
				if (next_target.seen_Y)
					home_y_positive();
				if (next_target.seen_Z)
					home_z_positive();
				break;

				// unknown gcode: spit an error
			default:
				sersendf_P(PSTR("E: Bad G-code %d"), next_target.G);
				// newline is sent from gcode_parse after we return
				return;
		}
	}
	else if (next_target.seen_M) {
		uint8_t i;

		switch (next_target.M) {
			case 0:
				//? --- M0: machine stop ---
				//?
				//? Example: M0
				//?
				//? http://linuxcnc.org/handbook/RS274NGC_3/RS274NGC_33a.html#1002379
				//? Unimplemented, especially the restart after the stop. Fall trough to M2.
				//?

			case 2:
      case 18:
      case 84: // For compatibility with slic3rs default end G-code.
				//? --- M2: program end ---
				//?
				//? Example: M2
				//?
				//? http://linuxcnc.org/handbook/RS274NGC_3/RS274NGC_33a.html#1002379
				//?
				queue_wait();
				for (i = 0; i < NUM_HEATERS; i++)
					temp_set(i, 0);
				power_off();
				break;

			case 112:
				//? --- M112: Emergency Stop ---
				//?
				//? Example: M112
				//?
				//? Any moves in progress are immediately terminated, then RepRap shuts down.  All motors and heaters are turned off.
				//? It can be started again by pressing the reset button on the master microcontroller.  See also M0.
				//?
				emergency_stop();
				break;

			case 6:
				//? --- M6: tool change ---
				//?
				//? Undocumented.
				tool = next_tool;
				break;

			case 82:
				//? --- M82 - Set E codes absolute ---
				//?
				//? This is the default and overrides G90/G91.
				//? M82/M83 is not documented in the RepRap wiki, behaviour
				//? was taken from Sprinter as of March 2012.
				//?
				//? While E does relative movements, it doesn't change its
				//? position in the coordinate system. See also comment on G90.
				//?

				// No wait_queue() needed.
				next_target.option_e_relative = 0;
				break;

			case 83:
				//? --- M83 - Set E codes relative ---
				//?
				//? Counterpart to M82.
				//?

				// No wait_queue() needed.
				next_target.option_e_relative = 1;
				break;

			// M17- Enable/Power all stepper motors
			case 17:
                power_on();
				break;

			// M3/M101- extruder on
			case 3:
			case 101:
				//? --- M101: extruder on ---
				//?
				//? Undocumented.
				if (temp_achieved() == 0) {
					enqueue(NULL);
				}
				#ifdef DC_EXTRUDER
					heater_set(DC_EXTRUDER, DC_EXTRUDER_PWM);
				#elif E_STARTSTOP_STEPS > 0
					do {
						// backup feedrate, move E very quickly then restore feedrate
						backup_f = startpoint.F;
						startpoint.F = MAXIMUM_FEEDRATE_E;
						SpecialMoveE(E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E);
						startpoint.F = backup_f;
					} while (0);
				#endif
				break;

			// M102- extruder reverse

			// M5/M103- extruder off
			case 5:
			case 103:
				//? --- M103: extruder off ---
				//?
				//? Undocumented.
				#ifdef DC_EXTRUDER
					heater_set(DC_EXTRUDER, 0);
				#elif E_STARTSTOP_STEPS > 0
					do {
						// backup feedrate, move E very quickly then restore feedrate
						backup_f = startpoint.F;
						startpoint.F = MAXIMUM_FEEDRATE_E;
						SpecialMoveE(-E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E);
						startpoint.F = backup_f;
					} while (0);
				#endif
				break;

			case 104:
				//? --- M104: Set Extruder Temperature (Fast) ---
				//?
				//? Example: M104 S190
				//?
        //? Set the temperature of the current extruder to 190<sup>o</sup>C
        //? and return control to the host immediately (''i.e.'' before that
        //? temperature has been reached by the extruder). For waiting, see M116.
        //?
        //? Teacup supports an optional P parameter as a zero-based temperature
        //? sensor index to address (e.g. M104 P1 S100 will set the temperature
        //? of the heater connected to the second temperature sensor rather
        //? than the extruder temperature).
        //?
				if ( ! next_target.seen_S)
					break;
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        // else use the first available device
        #endif
				temp_set(next_target.P, next_target.S);
				break;

			case 105:
        //? --- M105: Get Temperature(s) ---
				//?
				//? Example: M105
				//?
        //? Request the temperature of the current extruder and the build base
        //? in degrees Celsius. For example, the line sent to the host in
        //? response to this command looks like
				//?
				//? <tt>ok T:201 B:117</tt>
				//?
        //? Teacup supports an optional P parameter as a zero-based temperature
        //? sensor index to address.
				//?
				#ifdef ENFORCE_ORDER
					queue_wait();
				#endif
				if ( ! next_target.seen_P)
					next_target.P = TEMP_SENSOR_none;
				temp_print(next_target.P);
				break;

			case 7:
			case 106:
				//? --- M106: Set Fan Speed / Set Device Power ---
				//?
				//? Example: M106 S120
				//?
				//? Control the cooling fan (if any).
				//?
        //? Teacup supports an optional P parameter as a zero-based heater
        //? index to address. The heater index can differ from the temperature
        //? sensor index, see config.h.

				#ifdef ENFORCE_ORDER
					// wait for all moves to complete
					queue_wait();
				#endif
        #ifdef HEATER_FAN
          if ( ! next_target.seen_P)
            next_target.P = HEATER_FAN;
        // else use the first available device
        #endif
				if ( ! next_target.seen_S)
					break;
        heater_set(next_target.P, next_target.S);
				break;

			case 110:
				//? --- M110: Set Current Line Number ---
				//?
				//? Example: N123 M110
				//?
				//? Set the current line number to 123.  Thus the expected next line after this command will be 124.
				//? This is a no-op in Teacup.
				//?
				break;

			#ifdef	DEBUG
			case 111:
				//? --- M111: Set Debug Level ---
				//?
				//? Example: M111 S6
				//?
				//? Set the level of debugging information transmitted back to the host to level 6.  The level is the OR of three bits:
				//?
				//? <Pre>
				//? #define         DEBUG_PID       1
				//? #define         DEBUG_DDA       2
				//? #define         DEBUG_POSITION  4
				//? </pre>
				//?
				//? This command is only available in DEBUG builds of Teacup.

				if ( ! next_target.seen_S)
					break;
				debug_flags = next_target.S;
				break;
			#endif

			case 114:
				//? --- M114: Get Current Position ---
				//?
				//? Example: M114
				//?
				//? This causes the RepRap machine to report its current X, Y, Z and E coordinates to the host.
				//?
				//? For example, the machine returns a string such as:
				//?
				//? <tt>ok C: X:0.00 Y:0.00 Z:0.00 E:0.00</tt>
				//?
				#ifdef ENFORCE_ORDER
					// wait for all moves to complete
					queue_wait();
				#endif
				update_current_position();
				sersendf_P(PSTR("X:%lq,Y:%lq,Z:%lq,E:%lq,F:%lu"),
				                current_position.X, current_position.Y,
				                current_position.Z, current_position.E,
				                current_position.F);

				#ifdef	DEBUG
					if (DEBUG_POSITION && (debug_flags & DEBUG_POSITION)) {
						sersendf_P(PSTR(",c:%lu}\nEndpoint: X:%ld,Y:%ld,Z:%ld,E:%ld,F:%lu,c:%lu}"),
						                movebuffer[mb_tail].c, movebuffer[mb_tail].endpoint.X,
						                movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z,
						                movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F,
						#ifdef ACCELERATION_REPRAP
							movebuffer[mb_tail].end_c
						#else
							movebuffer[mb_tail].c
						#endif
						);
						print_queue();
					}
				#endif /* DEBUG */

				// newline is sent from gcode_parse after we return
				break;

			case 115:
				//? --- M115: Get Firmware Version and Capabilities ---
				//?
				//? Example: M115
				//?
				//? Request the Firmware Version and Capabilities of the current microcontroller
				//? The details are returned to the host computer as key:value pairs separated by spaces and terminated with a linefeed.
				//?
				//? sample data from firmware:
				//?  FIRMWARE_NAME:Teacup FIRMWARE_URL:http://github.com/triffid/Teacup_Firmware/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1 TEMP_SENSOR_COUNT:1 HEATER_COUNT:1
				//?

				sersendf_P(PSTR("FIRMWARE_NAME:Teacup FIRMWARE_URL:http://github.com/triffid/Teacup_Firmware/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:%d TEMP_SENSOR_COUNT:%d HEATER_COUNT:%d"), 1, NUM_TEMP_SENSORS, NUM_HEATERS);
				// newline is sent from gcode_parse after we return
				break;

			case 116:
				//? --- M116: Wait ---
				//?
				//? Example: M116
				//?
				//? Wait for temperatures and other slowly-changing variables to arrive at their set values.

				enqueue(NULL);
				break;

      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;

      #ifdef EECONFIG
			case 130:
				//? --- M130: heater P factor ---
				//? Undocumented.
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        // else use the first available device
        #endif
				if (next_target.seen_S)
					pid_set_p(next_target.P, next_target.S);
				break;

			case 131:
				//? --- M131: heater I factor ---
				//? Undocumented.
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        #endif
				if (next_target.seen_S)
					pid_set_i(next_target.P, next_target.S);
				break;

			case 132:
				//? --- M132: heater D factor ---
				//? Undocumented.
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        #endif
				if (next_target.seen_S)
					pid_set_d(next_target.P, next_target.S);
				break;

			case 133:
				//? --- M133: heater I limit ---
				//? Undocumented.
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        #endif
				if (next_target.seen_S)
					pid_set_i_limit(next_target.P, next_target.S);
				break;

			case 134:
				//? --- M134: save PID settings to eeprom ---
				//? Undocumented.
				heater_save_settings();
				break;
      #endif /* EECONFIG */

			#ifdef	DEBUG
			case 136:
				//? --- M136: PRINT PID settings to host ---
				//? Undocumented.
				//? This comand is only available in DEBUG builds.
        #ifdef HEATER_EXTRUDER
				if ( ! next_target.seen_P)
					next_target.P = HEATER_EXTRUDER;
				heater_print(next_target.P);
        #endif
				break;
			#endif

			case 140:
				//? --- M140: Set heated bed temperature ---
				//? Undocumented.
				#ifdef	HEATER_BED
					if ( ! next_target.seen_S)
						break;
					temp_set(HEATER_BED, next_target.S);
				#endif
				break;

			#ifdef	DEBUG
			case 240:
				//? --- M240: echo off ---
				//? Disable echo.
				//? This command is only available in DEBUG builds.
				debug_flags &= ~DEBUG_ECHO;
				serial_writestr_P(PSTR("Echo off"));
				// newline is sent from gcode_parse after we return
				break;

			case 241:
				//? --- M241: echo on ---
				//? Enable echo.
				//? This command is only available in DEBUG builds.
				debug_flags |= DEBUG_ECHO;
				serial_writestr_P(PSTR("Echo on"));
				// newline is sent from gcode_parse after we return
				break;

			#endif /* DEBUG */
				
			#ifdef PID_AUTOTUNE
			case 303:
				//? --- M303: PID autotune ---
				//? Perform pid autotune procedure.
				//? Hotend Usage: M303 S<temperature> C<cycles> Bed Usage: M303 E-1 C<cycles> S<temperature> Example: M303 C8 S175
			{
				uint32_t temp = 150*4;
				int32_t e = 0;
				uint32_t c = 8;
				
				if (next_target.seen_E)
					e = next_target.target.E;
				if (e < 0)
					temp = 70;
				
				if (next_target.seen_S) temp = next_target.S;
				if (next_target.seen_C) c = next_target.C;
				PID_autotune(temp, e, c);
			}
			#endif

				// unknown mcode: spit an error
			default:
				sersendf_P(PSTR("E: Bad M-code %d"), next_target.M);
				// newline is sent from gcode_parse after we return
		} // switch (next_target.M)
	} // else if (next_target.seen_M)
} // process_gcode_command()
Пример #5
0
void read_handler(boost::system::error_code ec, std::size_t bytes_transferred)
{
	if (!ec) {
		ROS_INFO("Received %d bytes", (int)bytes_transferred);
		
		lunabotics::proto::Telecommand tc;
		
		if (!tc.ParseFromArray(buffer.data(), bytes_transferred)) {
			ROS_ERROR("Failed to parse Telecommand object");
			emergency_stop();
			return;
		}
		
		lunabotics::Connection connectionMsg;
		connectionMsg.port = tc.reply_port();
		connectionMsg.ip = sock.remote_endpoint().address().to_string();
		connPublisher.publish(connectionMsg);
		
		switch(tc.type()) {
			case lunabotics::proto::Telecommand::SET_AUTONOMY: {
				
				ROS_INFO("%s autonomy", tc.autonomy_data().enabled() ? "Enabling" : "Disabling");
				
				std_msgs::Bool autonomyMsg;
				autonomyMsg.data = tc.autonomy_data().enabled();
				autonomyPublisher.publish(autonomyMsg);
			}
			break;
			
			case lunabotics::proto::Telecommand::STEERING_MODE: {
				
				lunabotics::proto::SteeringModeType type = tc.steering_mode_data().type();
				
				ROS_INFO("Switching control mode to %s", steeringModeToString(type).c_str());
				
				lunabotics::SteeringMode controlModeMsg;
				controlModeMsg.mode = type;
				controlModeMsg.distance_accuracy = tc.steering_mode_data().position_accuracy();
				controlModeMsg.angle_accuracy = tc.steering_mode_data().heading_accuracy();
				controlModeMsg.linear_speed_limit = tc.steering_mode_data().max_linear_velocity();
				controlModeMsg.bezier_segments = tc.steering_mode_data().bezier_curve_segments();
				controlModePublisher.publish(controlModeMsg);
			}
			break;
			
			case lunabotics::proto::Telecommand::TELEOPERATION: {
				lunabotics::Teleoperation teleopMsg;
				teleopMsg.forward = tc.teleoperation_data().forward();
				teleopMsg.backward = tc.teleoperation_data().backward();
				teleopMsg.left = tc.teleoperation_data().left();
				teleopMsg.right = tc.teleoperation_data().right();
				teleoperationPublisher.publish(teleopMsg);
			}
			break;
			
			case lunabotics::proto::Telecommand::DEFINE_ROUTE: {
				lunabotics::Goal goalMsg;
				const lunabotics::proto::Telecommand::DefineRoute route = tc.define_route_data();
	            for (int i = 0; i < route.waypoints_size(); i++) {
	                const lunabotics::proto::Point waypoint = route.waypoints(i);
	                geometry_msgs::Point pt = lunabotics::geometry_msgs_Point_from_Point(lunabotics::CreatePoint(waypoint.x(), waypoint.y()));
					goalMsg.waypoints.push_back(pt);
					ROS_INFO("Navigation to (%.1f,%.1f)", pt.x, pt.y);
				}
				goalPublisher.publish(goalMsg);
			}
			break;
			
			case lunabotics::proto::Telecommand::REQUEST_MAP: {
				ROS_INFO("Receiving map request");
				std_msgs::Empty emptyMsg;
				mapRequestPublisher.publish(emptyMsg);
			}
			break;
			
			case lunabotics::proto::Telecommand::ADJUST_PID: {
				lunabotics::PID pidMsg;
				pidMsg.p = tc.adjust_pid_data().p();
				pidMsg.i = tc.adjust_pid_data().i();
				pidMsg.d = tc.adjust_pid_data().d();
				pidMsg.feedback_min_offset = tc.adjust_pid_data().feedback_min_offset();
				pidMsg.feedback_multiplier = tc.adjust_pid_data().feedback_multiplier();
				pidMsg.feedforward_min_offset = tc.adjust_pid_data().feedforward_min_offset();
				pidMsg.feedforward_fraction = tc.adjust_pid_data().feedforward_fraction();
				pidPublisher.publish(pidMsg);
			}
			break;
			
			case lunabotics::proto::Telecommand::ADJUST_WHEELS: {
				switch (tc.all_wheel_control_data().all_wheel_type()) {
					case lunabotics::proto::AllWheelControl::EXPLICIT: {
						lunabotics::proto::AllWheelState::Wheels driving = tc.all_wheel_control_data().explicit_data().driving();
						lunabotics::proto::AllWheelState::Wheels steering = tc.all_wheel_control_data().explicit_data().steering();
						
						float left_front = steering.left_front();
						float right_front = steering.right_front();
						float left_rear = steering.left_rear();
						float right_rear = steering.right_rear();
						lunabotics::validateAngles(left_front, right_front, left_rear, right_rear);
						
						
						lunabotics::AllWheelState msg;
						msg.driving.left_front = driving.left_front();
						msg.driving.right_front = driving.right_front();
						msg.driving.left_rear = driving.left_rear();
						msg.driving.right_rear = driving.right_rear();
						msg.steering.left_front = left_front;
						msg.steering.right_front = right_front;
						msg.steering.left_rear = left_rear;
						msg.steering.right_rear = right_rear;
						allWheelPublisher.publish(msg);
					}
					break;
					
					case lunabotics::proto::AllWheelControl::PREDEFINED: {
						lunabotics::AllWheelCommon msg;
						msg.predefined_cmd = tc.all_wheel_control_data().predefined_data().command();
						msg.wheel_velocity = DEFAULT_WHEEL_VELOCITY;
						allWheelCommonPublisher.publish(msg);
					}
					break;
					
					case lunabotics::proto::AllWheelControl::ICR: {
						lunabotics::ICRControl msg;
						msg.ICR.x = tc.all_wheel_control_data().icr_data().icr().x();
						msg.ICR.y = tc.all_wheel_control_data().icr_data().icr().y();
						msg.velocity = tc.all_wheel_control_data().icr_data().velocity();
						ICRPublisher.publish(msg);
					}
					break;
					
					case lunabotics::proto::AllWheelControl::CRAB: {
						lunabotics::CrabControl msg;
						msg.heading = tc.all_wheel_control_data().crab_data().heading();
						msg.velocity = tc.all_wheel_control_data().crab_data().velocity();
						CrabPublisher.publish(msg);
					}
					break;
					
					default:
					break;
				}
			}
			break;
			
			default:
			break;
		}
	}
	else if (ec.value() == boost::asio::error::eof) {
		ROS_INFO("Connection closed by client");
	}
	else {
		ROS_WARN("Failed to read data. Error code %s", ec.message().c_str());
	}
	sock.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
	sock.close();
	acceptor.async_accept(sock, accept_handler); 
}
Пример #6
0
void CommandeGen::emerg_stop(){
    m_status = emergency_stop() ;
}
Пример #7
0
/// called every 10ms from clock.c - check all temp sensors that are ready for checking
void temp_sensor_tick() {
	temp_sensor_t i = 0;
	for (; i < NUM_TEMP_SENSORS; i++) {
		if (temp_sensors_runtime[i].next_read_time) {
			temp_sensors_runtime[i].next_read_time--;
		}
		else {
			uint16_t	temp = 0;
			#ifdef	TEMP_MAX31855
			uint32_t value = 0;
			struct max31855_plat_data *max31855;
			#endif
			//time to deal with this temp sensor
			switch(temp_sensors[i].temp_type) {
				#ifdef	TEMP_MAX31855
				case TT_MAX31855:
				#ifdef __arm__
				        max31855 = (struct max31855_plat_data*)temp_sensors[i].plat_data;
					spiAcquireBus(max31855->bus);
					spiStart(max31855->bus, max31855->config);
					spiSelect(max31855->bus);
					spiReceive(max31855->bus, 4, &value);
					spiUnselect(max31855->bus);
					spiReleaseBus(max31855->bus);

					value = SWAP_UINT32(value);

					temp_sensors_runtime[i].temp_flags = 0;
					if (value & (1 << 16)) {
                                        #ifdef HALT_ON_TERMOCOUPLE_FAILURE
						emergency_stop();
                                        #endif
					}
					else {
						temp = value >> 18;
						if (temp & (1 << 13))
							temp = 0;
					}
				#else
					temp = 0;
				#endif

					break;
				#endif
				#ifdef	TEMP_MAX6675
				case TT_MAX6675:
					#ifdef	PRR
						PRR &= ~MASK(PRSPI);
					#elif defined PRR0
						PRR0 &= ~MASK(PRSPI);
					#endif

					SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0);

					// enable TT_MAX6675
					WRITE(SS, 0);

					// No delay required, see
					// https://github.com/triffid/Teacup_Firmware/issues/22

					// read MSB
					SPDR = 0;
					for (;(SPSR & MASK(SPIF)) == 0;);
					temp = SPDR;
					temp <<= 8;

					// read LSB
					SPDR = 0;
					for (;(SPSR & MASK(SPIF)) == 0;);
					temp |= SPDR;

					// disable TT_MAX6675
					WRITE(SS, 1);

					temp_sensors_runtime[i].temp_flags = 0;
					if ((temp & 0x8002) == 0) {
						// got "device id"
						temp_sensors_runtime[i].temp_flags |= PRESENT;
						if (temp & 4) {
							// thermocouple open
							temp_sensors_runtime[i].temp_flags |= TCOPEN;
						}
						else {
							temp = temp >> 3;
						}
					}

					// this number depends on how frequently temp_sensor_tick is called. the MAX6675 can give a reading every 0.22s, so set this to about 250ms
					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_MAX6675	*/

				#ifdef	TEMP_THERMISTOR
				case TT_THERMISTOR:
					do {
						uint8_t j, table_num;
						//Read current temperature
						temp = analog_read(i);
						// for thermistors the thermistor table number is in the additional field
						table_num = temp_sensors[i].additional;

						//Calculate real temperature based on lookup table
						for (j = 1; j < NUMTEMPS; j++) {
							if (pgm_read_word(&(temptable[table_num][j][0])) > temp) {
								// Thermistor table is already in 14.2 fixed point
								#ifndef	EXTRUDER
								if (DEBUG_PID && (debug_flags & DEBUG_PID))
									sersendf_P(PSTR("pin:%d Raw ADC:%d table entry: %d"),temp_sensors[i].temp_pin,temp,j);
								#endif
								// Linear interpolating temperature value
								// y = ((x - x₀)y₁ + (x₁-x)y₀ ) / (x₁ - x₀)
								// y = temp
								// x = ADC reading
								// x₀= temptable[j-1][0]
								// x₁= temptable[j][0]
								// y₀= temptable[j-1][1]
								// y₁= temptable[j][1]
								// y =
								// Wikipedia's example linear interpolation formula.
								temp = (
								//     ((x - x₀)y₁
									((uint32_t)temp - pgm_read_word(&(temptable[table_num][j-1][0]))) * pgm_read_word(&(temptable[table_num][j][1]))
								//                 +
									+
								//                   (x₁-x)
									(pgm_read_word(&(temptable[table_num][j][0])) - (uint32_t)temp)
								//                         y₀ )
									* pgm_read_word(&(temptable[table_num][j-1][1])))
								//                              /
									/
								//                                (x₁ - x₀)
									(pgm_read_word(&(temptable[table_num][j][0])) - pgm_read_word(&(temptable[table_num][j-1][0])));
								#ifndef	EXTRUDER
								if (DEBUG_PID && (debug_flags & DEBUG_PID))
									sersendf_P(PSTR(" temp:%d.%d"),temp/4,(temp%4)*25);
								#endif
								break;
							}
						}
						#ifndef	EXTRUDER
						if (DEBUG_PID && (debug_flags & DEBUG_PID))
							sersendf_P(PSTR(" Sensor:%d\n"),i);
						#endif


						//Clamp for overflows
						if (j == NUMTEMPS)
							temp = temptable[table_num][NUMTEMPS-1][1];

						temp_sensors_runtime[i].next_read_time = 0;
					} while (0);
					break;
				#endif	/* TEMP_THERMISTOR */

				#ifdef	TEMP_AD595
				case TT_AD595:
					temp = analog_read(i);

					// convert
					// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
					temp = (temp * 500L) >> 8;

					temp_sensors_runtime[i].next_read_time = 0;

					break;
				#endif	/* TEMP_AD595 */

				#ifdef	TEMP_PT100
				case TT_PT100:
					#warning TODO: PT100 code
					break
				#endif	/* TEMP_PT100 */

				#ifdef	TEMP_INTERCOM
				case TT_INTERCOM:
					temp = read_temperature(temp_sensors[i].temp_pin);

					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_INTERCOM */

				#ifdef	TEMP_DUMMY
				case TT_DUMMY:
					temp = temp_sensors_runtime[i].last_read_temp;

					if (temp_sensors_runtime[i].target_temp > temp)
						temp++;
					else if (temp_sensors_runtime[i].target_temp < temp)
						temp--;

					temp_sensors_runtime[i].next_read_time = 0;

					break;
				#endif	/* TEMP_DUMMY */

				default: /* prevent compiler warning */
					break;
			}
			/* Exponentially Weighted Moving Average alpha constant for smoothing
			   noisy sensors. Instrument Engineer's Handbook, 4th ed, Vol 2 p126
			   says values of 0.05 to 0.1 for TEMP_EWMA are typical. */
			#ifndef TEMP_EWMA
				#define TEMP_EWMA 1.0
			#endif
			#define EWMA_SCALE  1024L
			#define EWMA_ALPHA  ((long) (TEMP_EWMA * EWMA_SCALE))
			temp_sensors_runtime[i].last_read_temp = (uint16_t) ((EWMA_ALPHA * temp +
			  (EWMA_SCALE-EWMA_ALPHA) * temp_sensors_runtime[i].last_read_temp
			                                         ) / EWMA_SCALE);
		}
		if (labs((int16_t)(temp_sensors_runtime[i].last_read_temp - temp_sensors_runtime[i].target_temp)) < (TEMP_HYSTERESIS*4)) {
			if (temp_sensors_runtime[i].temp_residency < (TEMP_RESIDENCY_TIME*120))
				temp_sensors_runtime[i].temp_residency++;
		}
		else {
			// Deal with flakey sensors which occasionally report a wrong value
			// by setting residency back, but not entirely to zero.
			if (temp_sensors_runtime[i].temp_residency > 10)
				temp_sensors_runtime[i].temp_residency -= 10;
			else
				temp_sensors_runtime[i].temp_residency = 0;
		}

		if (temp_sensors[i].heater < NUM_HEATERS) {
			heater_tick(temp_sensors[i].heater, temp_sensors[i].temp_type, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp);
		}

    if (DEBUG_PID && (debug_flags & DEBUG_PID))
      sersendf_P(PSTR("DU temp: {%d %d %d.%d}"), i,
                 temp_sensors_runtime[i].last_read_temp,
                 temp_sensors_runtime[i].last_read_temp / 4,
                 (temp_sensors_runtime[i].last_read_temp & 0x03) * 25);
	}
Пример #8
0
RudderMotor::~RudderMotor() 
{
	emergency_stop();
    can_close();
}
Пример #9
0
//
// Top level order handler
//
void process_command()
{
  if (is_stopped && !stopped_is_acknowledged && order_code != ORDER_RESUME)
  {
    send_stopped_response();
    return;
  }

  // we allow a sequence of write configuration commands
  // to be set as configured as a group. For instance,
  // writing the following sequence:
  // device.stepper.0.enable_pin=48
  // device.stepper.0.enable_invert=1
  // ...
  // will only result in the stepper configuration being applied when all
  // attributes have been applied.
  if (firmware_configuration_change_made || !final_firmware_configuration_update_done)
  {
    if (!final_firmware_configuration_update_done
        && (order_code == ORDER_SET_HEATER_TARGET_TEMP
            || order_code == ORDER_SET_OUTPUT_SWITCH_STATE
            || order_code == ORDER_SET_PWM_OUTPUT_STATE
            || order_code == ORDER_SET_OUTPUT_TONE
            || order_code == ORDER_ACTIVATE_STEPPER_CONTROL
            || order_code == ORDER_ENABLE_DISABLE_STEPPERS
            || order_code == ORDER_QUEUE_COMMAND_BLOCKS))
    {
      // assume that once devices are activated then initial firmware
      // configuration is complete and EEPROM state should be updated
      firmware_configuration_change_made = false;
      final_firmware_configuration_update_done = true;
      update_firmware_configuration(true);
    }
    else if (firmware_configuration_change_made
        && order_code != ORDER_WRITE_FIRMWARE_CONFIG_VALUE)
    {
      // update individual device states once firmware configuration
      // block is done
      firmware_configuration_change_made = false;
      update_firmware_configuration(false);
    }
  }

  switch (order_code)
  {
  case ORDER_RESET:
    emergency_stop(PARAM_STOPPED_CAUSE_USER_REQUEST);
    die();
    break;
  case ORDER_RESUME:
    handle_resume_order();
    break;
  case ORDER_REQUEST_INFORMATION:
    handle_request_information_order();
    break;
  case ORDER_DEVICE_COUNT:
    handle_device_count_order();
    break;
  case ORDER_DEVICE_NAME:
    handle_device_name_order();
    break;
  case ORDER_DEVICE_STATUS:
    handle_device_status_order();
    break;
  case ORDER_REQUEST_TEMPERATURE_READING:
    handle_request_temperature_reading_order();
    break;
  case ORDER_GET_HEATER_CONFIGURATION:
    handle_get_heater_configuration_order();
    break;
  case ORDER_CONFIGURE_HEATER:
    handle_configure_heater_order();
    break;
  case ORDER_SET_HEATER_TARGET_TEMP:
    handle_set_heater_target_temperature_order();
    break;
  case ORDER_GET_INPUT_SWITCH_STATE:
    handle_get_input_switch_state_order();
    break;
  case ORDER_SET_OUTPUT_SWITCH_STATE:
    handle_set_output_switch_state_order();
    break;
  case ORDER_SET_PWM_OUTPUT_STATE:
    handle_set_pwm_output_state_order();
    break;
  case ORDER_SET_OUTPUT_TONE:
    handle_set_output_tone_order();
    break;
  case ORDER_WRITE_FIRMWARE_CONFIG_VALUE:
    firmware_configuration_change_made = true;
    handle_write_firmware_configuration_value_order();
    break;
  case ORDER_READ_FIRMWARE_CONFIG_VALUE:
    // note: get_command() already makes the end of the command (ie. name) null-terminated
    handle_firmware_configuration_request((const char *)&parameter_value[0], 0);
    break;
  case ORDER_TRAVERSE_FIRMWARE_CONFIG:
    // note: get_command() already makes the end of the command (ie. name) null-terminated
    handle_firmware_configuration_traversal((const char *)&parameter_value[0]);
    break;
  case ORDER_GET_FIRMWARE_CONFIG_PROPERTIES:
    // note: get_command() already makes the end of the command (ie. name) null-terminated
    handle_firmware_configuration_value_properties((const char *)&parameter_value[0]);
    break;
  case ORDER_EMERGENCY_STOP:
    emergency_stop(PARAM_STOPPED_CAUSE_USER_REQUEST);
    send_OK_response();
    break;
  case ORDER_ACTIVATE_STEPPER_CONTROL:
    handle_activate_stepper_control_order();
    break;
  case ORDER_CONFIGURE_ENDSTOPS:
    handle_configure_endstops_order();
    break;
  case ORDER_ENABLE_DISABLE_STEPPERS:
    handle_enable_disable_steppers_order();
    break;
  case ORDER_ENABLE_DISABLE_ENDSTOPS:
    handle_enable_disable_endstops_order();
    break;
  case ORDER_QUEUE_COMMAND_BLOCKS:
    enqueue_command();
    break;
  case ORDER_CLEAR_COMMAND_QUEUE:
    handle_clear_command_queue_order();
    break;
  case ORDER_CONFIGURE_AXIS_MOVEMENT_RATES:
    handle_configure_axis_movement_rates_order();
    break;
  case ORDER_CONFIGURE_UNDERRUN_PARAMS:
    handle_configure_underrun_params_order();
    break;
  default:
    send_app_error_response(PARAM_APP_ERROR_TYPE_UNKNOWN_ORDER, 0);
    break;
  }

}
Пример #10
0
void loop()
{

    // quickly scan through baudrates until we receive a valid packet within timeout period
#if 0 // the baud rate change still isn't working for some reason.
    if (autodetect_baudrates_index != 0xFF)
    {
        if (millis() - first_rcvd_time > MAX_FRAME_COMPLETION_DELAY_MS * 1.5) // make sure its not a multiple of 100ms
        {
            PSERIAL.end();
            PSERIAL.flush();
            autodetect_baudrates_index += 1;
            if (autodetect_baudrates_index >= NUM_ARRAY_ELEMENTS(autodetect_baudrates))
                autodetect_baudrates_index = 0;
            PSERIAL.begin(pgm_read_dword(&autodetect_baudrates[autodetect_baudrates_index]));
            recv_buf_len = 0;
            first_rcvd_time = millis();
        }
    }
#endif

    if (get_command())
    {
        autodetect_baudrates_index = 0xFF;
        last_order_time = millis();
        is_host_active = true;
        order_code = recv_buf[PM_ORDER_BYTE_OFFSET];
        control_byte = recv_buf[PM_CONTROL_BYTE_OFFSET];
        parameter_length = recv_buf[PM_LENGTH_BYTE_OFFSET]-2;

#if TRACE_ORDER
        DEBUGPGM("\nOrder(");
        DEBUG_F(order_code, HEX);
        DEBUGPGM(", plen=");
        DEBUG_F(parameter_length, DEC);
        DEBUGPGM(", cb=");
        DEBUG_F(control_byte, HEX);
        DEBUGPGM("):");
        for (uint8_t i = 0; i < parameter_length; i++)
        {
            DEBUG_CH(' ');
            DEBUG_F(recv_buf[i], HEX);
        }
        DEBUG_EOL();
#endif

        // does this match the sequence number of the last reply
        if ((control_byte & CONTROL_BYTE_SEQUENCE_NUMBER_MASK) ==
                (reply_control_byte & CONTROL_BYTE_SEQUENCE_NUMBER_MASK)
                && (control_byte & CONTROL_BYTE_ORDER_HOST_RESET_BIT) == 0
                && reply_control_byte != 0xFF)
        {
            if (!reply_started)
            {
                // resend last response
                reply_started = true;
                generate_response_send();
            }
            else
            {
                // this is an unexpected error case (matching sequence number but nothing to send)
                generate_response_transport_error_start(PARAM_FRAME_RECEIPT_ERROR_TYPE_UNABLE_TO_ACCEPT,
                                                        control_byte);
                generate_response_msg_addPGM(PMSG(MSG_ERR_NO_RESPONSE_TO_SEND));
                generate_response_send();
            }
        }
        else
        {
            reply_sent = false;

            process_command();

            if (!reply_sent)
            {
                send_app_error_response(PARAM_APP_ERROR_TYPE_FIRMWARE_ERROR,
                                        PMSG(MSG_ERR_NO_RESPONSE_GENERATED));
            }
        }
        recv_buf_len = 0;
    }

    // Idle loop activities

    // Check if heaters need to be updated?
    if (temp_meas_ready)
    {
        Device_TemperatureSensor::UpdateTemperatureSensors();
        Device_Heater::UpdateHeaters();
    }

    // Now check low-priority stuff
    uint32_t now = millis();
    if (now - last_idle_check > 1000) // checked every second
    {
#if !DEBUG_DISABLE_HOST_TIMEOUT
        // have we heard from the host within the timeout?
        if (now - last_order_time > (HOST_TIMEOUT_SECS * 1000) && is_host_active)
        {
            is_host_active = false;
            if (!is_stopped)
            {
                emergency_stop(PARAM_STOPPED_CAUSE_HOST_TIMEOUT);
            }
        }
#endif
#if TRACE_MOVEMENT
        print_movement_ISR_state();
#endif
        last_idle_check = now;
    }
}
Пример #11
0
SailMotor::~SailMotor() 
{
    rtx_message("SailMotor-Destructor has been called ... ");
	emergency_stop();
}