void hex_receiver::map (uint8_t a_code, void* p_object, base_data_receiver* p_receiver)
{
	// Create a new mapping object
	hex_data_type_to_pointer* p_new_map = new hex_data_type_to_pointer;
	p_new_map->code = a_code;
	p_new_map->p_obj = p_object;
	p_new_map->p_rcvr = p_receiver;

	// If the map was successfully created, insert the mapping object into the linked 
	// list of such objects. It seems easiest to put it in as the first item to be 
	// found in the list
	if (p_new_map != NULL)
	{
		if (p_first_map == NULL)
		{
			p_new_map->p_next = NULL;
		}
		else
		{
			p_new_map->p_next = p_first_map;
		}
		p_first_map = p_new_map;

		HXR_DBG (p_serial, PMS ("HXR map: ") << p_first_map->p_obj 
				 << hex << p_first_map->code << endl);
	}
	else
	{
		// If the map wasn't successfully created, complain if debugging
		HXR_DBG (p_serial, PMS ("hex_receiver::map() alloc error ") << endl);
	}
}
Ejemplo n.º 2
0
void task_brightness::run (void)
{
   // Make a variable which will hold times to use for precise task scheduling
   TickType_t previousTicks = xTaskGetTickCount ();

   // Create an analog to digital converter driver object and a variable in which to
   // store its output. The variable p_my_adc only exists within this run() method,
   // so the A/D converter cannot be used from any other function or method
   adc* p_my_adc = new adc (p_serial);

   // Configure counter/timer 3 as a PWM for LED brightness. First set the data
   // direction register so that the pin used for the PWM will be an output. The 
   // pin is Port E pin 4, which is also OC3B (Output Compare B for Timer 3)
   DDRE = (1 << 4);

   // To set 8-bit fast PWM mode we must set bits WGM30 and WGM32, which are in two
   // different registers (ugh). We use COM3B1 and Com3B0 to set up the PWM so that
   // the pin output will have inverted sense, that is, a 0 is on and a 1 is off; 
   // this is needed because the LED connects from Vcc to the pin. 
   TCCR3A |= (1 << WGM30) | (1 << COM3B1) | (1 << COM3B0);

   // The CS31 and CS30 bits set the prescaler for this timer/counter to run the
   // timer at F_CPU / 64
   TCCR3B |= (1 << WGM32) | (1 << CS31)  | (1 << CS30); 

   // This is the task loop for the brightness control task. This loop runs until the
   // power is turned off or something equally dramatic occurs
   for (;;)
   {
      // Read the A/D converter from channel 1
      uint16_t a2d_reading = p_my_adc->read_once(1);

      // Convert the A/D reading into a PWM duty cycle. The A/D reading is between 0
      // and 1023; the duty cycle should be between 0 and 255. Thus, divide by 4
      uint16_t duty_cycle = a2d_reading / 4;

      //print the Duty_Cycle in comparison to the Power Signal being pumped into set_power

      *p_serial <<PMS ("ADC Reading: ")<< a2d_reading <<dec <<endl
           <<PMS ("Power_Signal: ")<< duty_cycle <<dec <<endl;


      // Set the brightness. Since the PWM has already been set up, we only need to
      // put a new value into the duty cycle control register, which on an AVR is 
      // the output compare register for a given timer/counter
      OCR3B = duty_cycle;
      
      //OCR1B = duty_cycle;
      // Increment the run counter. This counter belongs to the parent class and can
      // be printed out for debugging purposes
      runs++;

      // This is a method we use to cause a task to make one run through its task
      // loop every N milliseconds and let other tasks run at other times
      delay_from_for_ms (previousTicks, 1000);
   }
}
Ejemplo n.º 3
0
emstream& operator << (emstream& serpt, hctl& hc20)
{
	// Prints info to the serial port
	serpt << PMS ("This HCTL-2000 is using these pins:")<< dec << endl 
	      << PMS ("OE pin: ")<< hc20.get_oe_port() << ":" << hc20.get_oe_pin() << endl
	      << PMS ("Sharable pins:") << endl
	      << PMS ("SEL pin: ")<< hc20.get_sel_port() << ":" << hc20.get_sel_pin() << endl
	      << PMS ("Data bus port: ") << hc20.get_data_port() << endl;

	return (serpt);
}
Ejemplo n.º 4
0
void task_hctl_2000::run (void)
{
  TickType_t prev = xTaskGetTickCount();
  while (1)
  {
    uint16_t val = counter->read();  
    uint8_t low = counter->get_low();
    uint8_t high = counter -> get_high();
    *p_serial << PMS("Current encoder reading: ") << dec << val << " = " << bin << val << endl;
    *p_serial << PMS("High Bits: ") << dec << high << " = " << bin << high << endl;
    *p_serial << PMS("Low Bits: ") << dec << low << " = " << bin << low << endl;
    delay_from_for_ms(prev, 1);
  }
}
Ejemplo n.º 5
0
void TaskBase::print_status (emstream& ser_dev)
{
	ser_dev.puts (pcTaskGetTaskName (handle));
	ser_dev.putchar ('\t');
	if (strlen ((const char*)(pcTaskGetTaskName (handle))) < 8)
	{
		ser_dev.putchar ('\t');
	}
	ser_dev << (uint8_t)(uxTaskPriorityGet (handle)) << PMS ("\t")
			<< get_state ()
		#if (INCLUDE_uxTaskGetStackHighWaterMark == 1)
			<< PMS ("\t") << uxTaskGetStackHighWaterMark(handle) << PMS ("/") 
			<< (size_t)(get_total_stack ()) << PMS ("\t")
		#endif
			<< PMS ("\t") << runs;
}
Ejemplo n.º 6
0
int main (void)
{
	// Disable the watchdog timer unless it's needed later. This is important because
	// sometimes the watchdog timer may have been left on...and it tends to stay on
	MCUSR = 0;
	wdt_disable ();

	// Configure a serial port which can be used by a task to print debugging infor-
	// mation, or to allow user interaction, or for whatever use is appropriate.  The
	// serial port will be used by the user interface task after setup is complete and
	// the task scheduler has been started by the function vTaskStartScheduler()
	rs232* p_ser_port = new rs232 (9600, 1);
	*p_ser_port << clrscr << PMS ("ME405 Lab 1 Program") << endl;

	// Create the queues and other shared data items here
	p_print_ser_queue = new TextQueue (32, "Print", p_ser_port, 10);

	// The user interface is at low priority; it could have been run in the idle task
	// but it is desired to exercise the RTOS more thoroughly in this test program
	new task_user ("UserInt", task_priority (1), 260, p_ser_port);

	// Create a task which reads the A/D and adjusts an LED's brightness accordingly
	new task_brightness ("Bright", task_priority (2), 280, p_ser_port);

	// Here's where the RTOS scheduler is started up. It should never exit as long as
	// power is on and the microcontroller isn't rebooted
	vTaskStartScheduler ();
}
Ejemplo n.º 7
0
/** @brief   This overloaded operator prints information about a motor driver. 
 *  @details It prints out appropriate information about the motor driver being delivered in the parameter.
 *  @param   serpt Reference to a serial port to which the printout will be printed
 *  @param   a2d   Reference to the motor driver which is being accessed
 *  @return  A reference to the same serial device on which we write information.
 *           This is used to string together things to write with @c << operators
 */
emstream& operator << (emstream& serpt, motor_driver& motdrv)
{
   // Prints info to serial
   serpt << PMS ("Motor Driver Input: ")<<endl;


   return (serpt);
}
Ejemplo n.º 8
0
void hex_dump_memory (uint8_t* start_address, uint8_t* end_address,
					  emstream* p_ser_dev)
{
	uint8_t byte_count;                     // Counts through the bytes in a line
	uint8_t temp_byte;                      // Holds a byte temporarily and obviously

	// Find the end address for the dump. Since C++ doesn't allow us to add two
	// pointers together, we convert the pointers into equivalent integers (this is
	// non-portable and may need to be changed for other processors!), add those
	// together, then convert back into a pointer

	// Print DUMP_BYTES_PER_LINE bytes on each line
	*p_ser_dev << hex;
	while (start_address < end_address)
	{
		// Print the line address 
		*p_ser_dev << (size_t)(start_address) << PMS ("  ");

		// Show a line full of data in hexadecimal format
		for (byte_count = 0; byte_count < DUMP_BYTES_PER_LINE; byte_count++)
		{
			*p_ser_dev << (uint8_t)(*start_address++);
			p_ser_dev->putchar (' ');
		}

		// Show the same line full of data in text format
		p_ser_dev->putchar (' ');
		for (start_address -= DUMP_BYTES_PER_LINE; byte_count > 0; byte_count--)
		{
			temp_byte = *start_address++;
			if (temp_byte == 0xA5)
			{
				p_ser_dev->putchar (' ');
			}
			else if (temp_byte >= ' ' && temp_byte <= '~')
			{
				p_ser_dev->putchar (temp_byte);
			}
			else
			{
				p_ser_dev->putchar ('.');
			}
		}

		// Put a return at the end of the line
		*p_ser_dev << endl;
	}
	*p_ser_dev << dec;
}
Ejemplo n.º 9
0
emstream& operator << (emstream& serpt, adc& a2d)
{
	// Right now this operator doesn't do anything useful. It should be made useful
	serpt << PMS ("The A/D converter registers have these settings:") 
		  << a2d.read_once (0) << endl
          << a2d.read_once (1) << endl
          << a2d.read_once (2) << endl
          << a2d.read_once (3) << endl
          << a2d.read_once (4) << endl
          << a2d.read_once (5) << endl
          << a2d.read_once (6) << endl
          << a2d.read_once (7) << endl;

	return (serpt);
}
Ejemplo n.º 10
0
int main (void)
{
    // Disable the watchdog timer unless it's needed later. This is important because
    // sometimes the watchdog timer may have been left on...and it tends to stay on
    MCUSR = 0;
    wdt_disable ();

    // Configure a serial port which can be used by a task to print debugging infor-
    // mation, or to allow user interaction, or for whatever use is appropriate.  The
    // serial port will be used by the user interface task after setup is complete and
    // the task scheduler has been started by the function vTaskStartScheduler()
    rs232* p_ser_port = new rs232 (9600, 1);
    // print this identifier line.
    *p_ser_port << clrscr << PMS ("ME405 Lab 2 Motor Controller Program") << endl;

    //initialize the A/D converter for potentiometer control
    adc* p_main_adc = new adc (p_ser_port);

    // Create the queues and other shared data items here
    p_print_ser_queue = new TextQueue (32, "Print", p_ser_port, 10);
    motor_directive = new TaskShare<uint8_t> ("Motor Directive");
    motor_power = new TaskShare<int16_t> ("Motor Power");
    motor_select = new TaskShare<uint8_t> ("Motor Select");

    //initialize to special value so no motor is affected yet
    motor_select -> put(NULL_MOTER);


    //initilaize two different motor driver pointers to pass into two tasks
    motor_driver* p_motor1 = new motor_driver(p_ser_port, &PORTC, &PORTC, &PORTB, &OCR1B, PC0, PC1, PC2, PB6);

    motor_driver* p_motor2 = new motor_driver(p_ser_port, &PORTD, &PORTD, &PORTB, &OCR1A, PD5, PD6, PD7, PB5);
    // The user interface is at low priority; it could have been run in the idle task
    // but it is desired to exercise the RTOS more thoroughly in this test program
    new task_user ("UserInt", task_priority (1), 260, p_ser_port);

    // Create tasks to control motors, given individual p_motors

    new task_motor ("Motor1", task_priority (2), 280, p_ser_port, p_motor1, p_main_adc, 1);

    new task_motor ("Motor2", task_priority (2), 280, p_ser_port, p_motor2, p_main_adc, 2);

    // Here's where the RTOS scheduler is started up. It should never exit as long as
    // power is on and the microcontroller isn't rebooted
    vTaskStartScheduler ();
}
Ejemplo n.º 11
0
emstream& operator << (emstream& serpt, adc& a2d)
{
	serpt << bin << PMS ("ADMUX : ") << ADMUX << PMS (" ADCSRA : ") << ADCSRA
	 << dec << endl;
	return (serpt);
}
Ejemplo n.º 12
0
void task_encoder::run (void)
{
   // Make a variable which will hold times to use for precise task scheduling
   TickType_t previousTicks = xTaskGetTickCount ();

   // Configure counter/timer 1 as a PWM for Motor Drivers.
   // COM1A1/COM1B1 to set to non inverting mode.
   // WGM10 to set to Fast PWM mode (only half ughhhhh)
   TCCR1A |= (1 << WGM10) | (1 << COM1A1) | (1 << COM1B1);
   // This is the second Timer/Counter Register
   // WGM12 (other half of Fast PWM)
   // CS11 Sets the presacler to 8 (010)
   TCCR1B |= (1 << WGM12) | (1 << CS11);

   // Create an analog to digital converter driver object and a variable in which to
   // store its output. The variable p_my_adc only exists within this run() method,
   // so the A/D converter cannot be used from any other function or method
   adc* p_adc = new adc (p_serial);

   //**  CREATE THE MOTOR DRIVERS  **//

   // create a pointer to a motor driver object and pass it addresses to PORTC, PORTB, OC1B and Pin Values for PC0, PC2, and PB6 as the PWM
   motor_driver* p_motor1 = new motor_driver(p_serial, &PORTC, &PORTC, &PORTB, &OCR1B, PC0, PC1, PC2, PB6);

   // create a pointer to a motor driver object and pass it addresses to PORTD, PORTB, OC1A and Pin Values for PD5, PD7, and PB5 as the PWM
   motor_driver* p_motor2 = new motor_driver(p_serial, &PORTD, &PORTD, &PORTB, &OCR1A, PD5, PD6, PD7, PB5);

   // The loop to contunially run the motors
   while (1)
   {
      // Read the A/D converter from channel 1
      uint16_t a2d_reading = p_adc->read_once(1);

      // Convert the A/D reading into a PWM duty cycle. The A/D reading is between 0
      // and 1023; the duty cycle should be between 0 and 255. Thus, divide by 4
      uint16_t duty_cycle = a2d_reading / 4;

      int16_t power = ((int16_t)duty_cycle * 1);

      //doesn't let the duty_cycle go to 0 because then the power is 0.
      if (duty_cycle == 0) {duty_cycle++;}
      //From 00 - 64 we want to decrease forwards
      //From 65 - 128 we want to increase backwards
      //From 129 - 192 we want to set both outs to high to set holding brake
      //From 193 - 255 we want to set both outs to low so that they don't affect the motor
      if (duty_cycle <= 64)
      {
         //forwards start from high speed to go to low speed
         power = 255 - (4 * duty_cycle);

         p_motor1->set_power(power);
         p_motor2->set_power(duty_cycle);
      }
      else if (duty_cycle > 64 && duty_cycle <= 128)
      {
         //backwards start from low speed to go to high speed
         power = -4 * (duty_cycle - 64);
         p_motor1->set_power(power);
         p_motor2->set_power(-1 * duty_cycle);
      }
      else if ( duty_cycle > 128 && duty_cycle <= 192)
      {
         //power stopping
         power = 4 * (duty_cycle - 128);
         p_motor1->brake(power);
         p_motor2->brake(power);
      }
      else
      {
         //free wheeling
         p_motor1->brake();
         p_motor2->brake();
      }

      *p_serial << PMS ("Duty_Cycle: ") << duty_cycle << dec << endl
                << PMS ("Power_Signal: ") << power << dec << endl;

      // Increment the run counter. This counter belongs to the parent class and can
      // be printed out for debugging purposes
      runs++;

      // This is a method we use to cause a task to make one run through its task
      // loop every N milliseconds and let other tasks run at other times
      delay_from_for_ms (previousTicks, 10);
   }
}
Ejemplo n.º 13
0
void print_task_list (emstream* ser_dev)
{
	// Print the first line with the top of the headings
	*ser_dev << PMS ("Task\t\t  \t ")
		#if (INCLUDE_uxTaskGetStackHighWaterMark == 1)
			<< PMS ("\tStack")
		#endif
			<< endl;

	// Print the second line with the rest of the headings
	*ser_dev << PMS ("Name\t\tPri.\tState")
		#if (INCLUDE_uxTaskGetStackHighWaterMark == 1)
			<< PMS ("\tFree/Total")
		#endif
			<< PMS ("\tRuns") << endl;

	// Print the third line which shows separators between headers and data
	*ser_dev << PMS ("----\t\t----\t-----")
		#if (INCLUDE_uxTaskGetStackHighWaterMark == 1)
			<< PMS ("\t----------")
		#endif
			<< PMS ("\t----") << endl;

	// Now have the tasks each print out their status. Tasks form a linked list, so
	// we only need to get the last task started and it will call the next, etc.
	if (last_created_task_pointer != NULL)
	{
		last_created_task_pointer->print_status_in_list (ser_dev);
	}

	// Have the idle task print out its information
	*ser_dev << PMS ("IDLE\t\t0\t-\t")
		#if (INCLUDE_uxTaskGetStackHighWaterMark == 1)
			<< uxTaskGetStackHighWaterMark (xTaskGetIdleTaskHandle ())
			<< PMS ("/") << configMINIMAL_STACK_SIZE << PMS ("\t\t-")
		#endif
			<< endl;
}
Ejemplo n.º 14
0
int main (void)
{
    // Disable the watchdog timer unless it's needed later. This is important because
    // sometimes the watchdog timer may have been left on...and it tends to stay on
    MCUSR = 0;
    wdt_disable ();
    // MAKE RESET INTERRUPT

    // time_stamp the_time_now;

    // Configure a serial port which can be used by a task to print debugging infor-
    // mation, or to allow user interaction, or for whatever use is appropriate.  The
    // serial port will be used by the user interface task after setup is complete and
    // the task scheduler has been started by the function vTaskStartScheduler()
    rs232* p_ser_port = new rs232 (9600, 1);
    // print this identifier line.
    *p_ser_port << clrscr << PMS ("ME405 Lego Car Comms Test") << endl;

    // set up USART0 on E0 and E1 for external comms
    // rs232* p_ser_bt = new rs232(0, 0);
    // UCSR0A |= (1 << U2X0); // set the double-speed bit
    // UBRR0 = 16; // set baud rate to 115200

    //initialize the A/D converter for potentiometer control
    // adc* p_main_adc = new adc (p_ser_port);

    // Create the queues and other shared data items here
    p_print_ser_queue = new TextQueue (32, "Print", p_ser_port, 10);

    /// Start Shares Motor Variables
    motor_setpoint = new TaskShare<int16_t> ("Motor SetPoint");
    motor_directive = new TaskShare<uint8_t> ("Motor Directive");
    motor_power = new TaskShare<int16_t> ("Motor Power");
    // Start Shares Encoder Variables
    encoder_count = new TaskShare<int32_t> ("Encoder Pulse Count");
    encoder_ticks_per_task = new TaskShare<int16_t> ("Encoder Pulse Per Time");
    // Start Shares IMU variables
    data_read = new TaskShare<uint32_t> ("imu data");

    // Start Shares Steering Variables
    steering_power = new TaskShare<int16_t> ("Steering Power");
    // Start Shares oystick Position Variables
    x_joystick = new TaskShare<int16_t> ("X Joystick Position");
    y_joystick = new TaskShare<int16_t> ("Y Joystick Position");
    // Start  Shares Gear Variables
    gear_state = new TaskShare<int16_t> ("Shift State");

    // new task_encoder ("EncoderControl", task_priority(5), 280, p_ser_port, p_hctl);

    new task_receiver ("REC", task_priority(5), 300, p_ser_port);

    //*p_ser_port << "Waiting.." << endl;


    //initialize to special value so no motor is affected yet
    //**DROPPING SUPPORT 2 MOTORS//
    //motor_select -> put(NULL_MOTER);

    // //initilaize two different motor driver pointers to pass into two tasks
    // motor_driver* p_motor1 = new motor_driver(p_ser_port, &PORTC, &PORTC, &PORTB, &OCR1B, PC0, PC1, PC2, PB6);

    // //USE TIMER AND COUNTER 3
    // // this is steering
    // servo_driver* p_steering_servo = new servo_driver(p_ser_port, &TCCR3A, &TCCR3B, &ICR3, &OCR3A, 8, 20000, PE3);
    // // this is shifting

    // //encoder_driver* p_encoder1 = new encoder_driver(p_ser_port, &EICRB, &EIMSK, &DDRE, ISC60, ISC70, INT6, INT7, PE6, PE7);

    // servo_driver* p_shift_servo = new servo_driver(p_ser_port, &TCCR3A, &TCCR3B, &ICR3, &OCR3B, 8, 20000, PE4);

    // // make instance of hctl_driver to count external ticks from hctl chip
    // hctl_driver* p_hctl = new hctl_driver(p_ser_port, &PORTA, &PORTC, 7, &PORTC, 6);

    // // make instance of imu_driver to be able to link to the BNO055
    // imu_driver* p_imu = new imu_driver(p_ser_port, &PORTD, &DDRD, 0, 1);
    // // temp method to read from IMU
    // int8_t tempsss = p_imu -> readIMU(0, 1);

    // shift_driver* p_local_shift = new shift_driver(p_ser_port, &EICRB, &EIMSK, &PORTE, ISC50, INT5, PE5);

    // // Create tasks to control motors, encoders, and IMUs
    // new task_user ("UserInt", task_priority (1), 260, p_ser_port);

    // new task_motor ("MotorControl", task_priority (2), 280, p_ser_port, p_motor1, p_main_adc, 1);

    // //start encoder and give the highest priority
    // new task_encoder ("EncoderControl", task_priority(5), 280, p_ser_port, p_hctl);

    // new task_steering ("SteeringControl", task_priority(3), 280, p_ser_port, p_steering_servo, 1);


    // new task_shift ("ShiftControl", task_priority(4), 280, p_ser_port,p_shift_servo, 1, p_local_shift);


    // // create a new PID manager for the motor, with K values of:
    // // Proportional = 1, Integral = 0, Derivative = 0, Windup = 0
    // // And the default saturation limits
    // new task_pid ("PID", task_priority(4), 280, p_ser_port, motor_setpoint, encoder_ticks_per_task, motor_power, 1024, 0, 0, 0, -1023, 1023);




    vTaskStartScheduler ();
}
Ejemplo n.º 15
0
/**
 * @brief      This method runs when the 'task_user' is called.
 *
 * @details    This method runs inifitely when the task is called so all logic
 *             is contained in here. A for(;;) loop runs until it gets to the
 *             end where it delays for 1 ms to allow other lower level
 *             priority tasks a chance to run.
 */
void task_user::run (void)
{
    time_stamp a_time;             // Holds the time so it can be displayed
    number_entered = 0;            // Holds a number being entered by user

    //
    for (;;)
    {
        switch (state)
        {
        // Initialize first task where we wait for
        case (0):
            printMainMenu();
            // If the user typed a character, read
            if (hasUserInput())
            {
                // In this switch statement, we respond to different characters as commands typed in by the user
                switch (char_in)
                {
                // The 't' command asks what time it is right now
                case ('m'):
                    *p_serial << PMS("->Selected: ") << char_in;
                    *p_serial
                            << endl
                            << endl
                            << PMS ("\t->Switching to Motor Module..")
                            << endl
                            << PMS ("\t->Clearing Registers and Menus..")
                            << endl
                            << PMS ("\t->Intializing Motors..")
                            << endl;

                    // Reset the visible menu flag
                    resetMenus();
                    // Sets the variable to true so it doesn't go into single module yet
                    in_main_motor_module = true;
                    // go to case 1 over all
                    transition_to(1);
                    break;
                // Enter encoder test module
                case ('e'):
                    *p_serial << PMS("->Selected: ") << char_in;
                    *p_serial
                            << ATERM_CLEAR_SCREEN << ATERM_CURSOR_TO_YX(1, 1)
                            << PMS ("\t->Switching to Encoder Module..")
                            << endl
                            << PMS ("\t->Clearing Registers and Menus..")
                            << endl
                            << PMS ("\t->Intializing Encoder..")
                            << endl << endl;

                    // Reset the visible menu flag
                    resetMenus();
                    // Sets the variable to true so it doesn't go into single module yet
                    in_encoder_module = true;
                    // go to case 1 over all
                    transition_to(3);
                    break;
                // The 't' command asks what time it is right now
                // Enter encoder test module
                case ('i'):
                    *p_serial << PMS("->Selected: ") << char_in;
                    *p_serial
                            << ATERM_CLEAR_SCREEN << ATERM_CURSOR_TO_YX(1, 1)
                            << PMS ("\t->Switching to IMU Module..")
                            << endl
                            << PMS ("\t->Clearing Registers and Menus..")
                            << endl
                            << PMS ("\t->Intializing IMU..")
                            << endl << endl;

                    // Reset the visible menu flag
                    resetMenus();
                    // Sets the variable to true so it doesn't go into single module yet
                    in_imu_module = true;
                    // go to case 1 over all
                    transition_to(4);
                    break;
                // The 't' command asks what time it is right now
                case ('t'):
                    *p_serial << (a_time.set_to_now ()) << endl;
                    break;

                // The 's' command asks for version and status information
                case ('s'):
                    show_status ();
                    break;
                // The 'd' means drive control
                case ('d'):
                    *p_serial << PMS("->Selected: ") << char_in;
                    *p_serial
                            << ATERM_CLEAR_SCREEN << ATERM_CURSOR_TO_YX(1, 1)
                            << PMS ("\t->Switching to Drive Mode..")
                            << endl << endl;
                    transition_to(5);
                    in_drive_mode = true;
                    resetMenus();
                    break;
                //case ('d'):
                // The 'h' command is a plea for help; '?' works also
                case ('h'):
                case ('?'):
                    print_help_message ();
                    break;

                // The 'n' command runs a test of entering a number
                case ('n'):
                    while (char_in != 'q')
                    {
                        *p_serial << PMS ("Enter decimal numeric digits, "
                                          "then RETURN or ESC") << endl;
                        getNumberInput();
                        *p_serial << endl << endl << PMS("\t->You Entered: ") << number_entered << endl;
                    }
                    break;

                // A control-C character causes the CPU to restart
                case (3):
                    *p_serial << PMS ("Resetting AVR") << endl;
                    wdt_enable (WDTO_120MS);
                    for (;;);
                    break;

                // If character isn't recognized, ask What's That Function?
                default:
                    *p_serial << '"' << char_in << PMS ("\": WTF?") << endl;
                    break;
                }; // End switch for characters
            } // End if a character was received

            break; // End of state 0

        // Motor Control BASE module
        case (1):
            if (in_main_motor_module) //first time here run menu and get input
            {
                // prints the menu for this module
                printMotorMenu();

                // user is going to input motor number or q
                getNumberInput();

                if (char_in == 'q')
                {
                    *p_serial << PMS("->Selected: ") << char_in << endl
                              << endl
                              << endl
                              << PMS("\t->Returning to Mission Control.. ")
                              << endl
                              << PMS("\t->Releasing Motors..") << endl
                              << PMS("\t->Resetting AVR..") << endl;
                    //wdt_enable (WDTO_120MS);
                    //for (;;);
                    //break;
                    //release motors
                    //motor_select->put(1);

                    //motor_directive -> put(FREEWHEEL);
                    //
                    // no longer in this module, leaving
                    in_main_motor_module = false;
                    transition_to(0);
                    resetMenus();
                    break;
                    //reset menu flag
                    //resetMenus();
                    // set the transition & wait for break
                    //transition_to(0);

                }
                // if the number entered is valid
                else if (isValidMotor(number_entered))
                {
                    // re print user input and give them confirmation message.
                    *p_serial
                            << endl
                            << endl
                            << PMS("\t->Switching to Control of Motor ") << number_entered << dec << PMS(".") << endl
                            << PMS ("\t->Return to the Main Motor Module to swap Motors.") << endl;
                    // set local motor select value
                    local_motor_select = number_entered;
                    //reset menus
                    resetMenus();
                    //set flag to off so we can go into the single motor module
                    in_main_motor_module = false;
                    // go back to the top of this menu
                    // since in_main_motor_module flag is set off, we will go into single motor control when this state reloops
                    transition_to(1);
                }
                else
                {
                    *p_serial << PMS("Try Again. ") << endl;
                    in_main_motor_module = true;

                }

                break;
            }
            if (!in_main_motor_module) //already were here now we go deeper
            {


                printSingleMotorOptions();
                // They now select the motor task
                if (hasUserInput())
                {
                    switch (char_in)
                    {
                    case ('s'):
                        *p_serial
                                << PMS("->Selected: ") << char_in << endl;
                        *p_serial
                                << endl
                                << PMS ("Enter the Power Value (-255 to 255);")
                                << endl
                                << PMS("  *Note: Negative Values = Reverse")
                                << endl;

                        //motor_directive -> put(1);
                        getNumberInput();
                        //setPower(motor_select->get(), number_entered);
                        setMotor(local_motor_select, (int16_t)number_entered, SETPOWER);
                        *p_serial
                                << endl << endl
                                << PMS ("\tPower set at ") << number_entered
                                << PMS(". ") << endl;

                        resetMenus();
                        printDashBoard();

                        //now that operation is complete, ask for more
                        *p_serial
                                << endl << PMS("->Choose Motor ")
                                << local_motor_select << PMS(" operation: ")
                                << PMS("\t(Press 'o' for options)")
                                << endl;
                        break;
                    case ('b'):
                        *p_serial
                                << PMS("->Selected: ") << char_in
                                << endl;
                        *p_serial
                                << PMS ("\t->Enter the Brake Force(0 - 255)")
                                << endl;
                        getNumberInput();
                        *p_serial
                                << endl << endl
                                << PMS ("\tBrake set at ") << number_entered
                                << PMS(". ") << endl;

                        setMotor(local_motor_select, number_entered, BRAKE);
                        resetMenus();

                        printDashBoard();
                        //now that operation is complete, ask for more
                        *p_serial
                                << endl << PMS("->Choose Motor ")
                                << local_motor_select << PMS(" operation: ")
                                << PMS("\t(Press 'o' for options)")
                                << endl;
                        break;
                    case ('f'):
                        *p_serial
                                << PMS("->Selected: ") << char_in << endl;
                        *p_serial
                                << PMS ("\t->Releasing Motor..") << endl;
                        setMotor(0, 0, FREEWHEEL);
                        resetMenus();
                        printDashBoard();
                        //now that operation is complete, ask for more
                        *p_serial
                                << endl << PMS("->Choose Motor ")
                                << local_motor_select << PMS(" operation: ")
                                << PMS("\t(Press 'o' for options)")
                                << endl;

                        break;
                    case ('p'):
                        *p_serial
                                << endl << PMS("->Selected: ")
                                << char_in << endl
                                << PMS("\t->Entering Potentiometer Control... ") << endl;
                        *p_serial << PMS ("\t->Potentiometer Activated.") << endl << endl;
                        *p_serial << endl << endl
                                  << PMS ("\t->Press 'q' to return to the Motor ") << local_motor_select << PMS(" Control")
                                  << endl << PMS ("\t->Press 'r' to refresh the DashBoard ") << endl;
                        transition_to(2);
                        resetMenus();
                        break;
                    case ('o'):
                        resetMenus();
                        printSingleMotorOptions();
                        break;
                    case ('q'):
                        *p_serial
                                << PMS("->Selected: ") << char_in << endl
                                << PMS(" Returning to Main Motor Module.. ")
                                << endl;
                        transition_to(1);
                        resetMenus();

                        in_main_motor_module = true;
                        break;
                    default:
                        *p_serial
                                << endl << PMS("'") << char_in
                                << PMS ("' is not a valid entry.") << endl;
                        *p_serial
                                << endl << PMS("->Choose Motor ")
                                << local_motor_select
                                << PMS(" operation: ") << endl;
                        break;
                    }
                }
            }

            break;
        //Potentiometer Mode
        case (2):
            if (hasUserInput())
            {
                if (char_in  == 'q')
                {
                    *p_serial << endl << PMS("->Selected: ") << char_in << endl;
                    transition_to(1);
                    resetMenus();
                    break;
                    //
                }
                if (char_in == 'r')
                {
                    *p_serial << endl << PMS("->Selected: ") << char_in << endl;
                    resetMenus();
                    printDashBoard();
                    *p_serial << endl << endl
                              << PMS ("\t->Press 'q' to return to the Motor ") << local_motor_select << PMS(" Control")
                              << endl << PMS ("\t->Press 'r' to refresh the DashBoard ") << endl;

                }
            }

            setMotor(local_motor_select, motor_power -> get(), POTENTIOMETER);
            printDashBoard();
            break;
        //for use later [3,4]
        case (3):
            if (in_encoder_module)
            {
                printEncoderModuleOptions();
                if (hasUserInput())
                    switch (char_in)
                    {
                    case ('q'):
                        *p_serial << ATERM_CLEAR_SCREEN << ATERM_BKG_WHITE
                                  << PMS("->Selected: ") << char_in << endl
                                  << endl
                                  << endl
                                  << PMS("\t->Returning to Mission Control.. ")
                                  << endl
                                  << PMS("\t->Releasing Encoder..") << endl;
                        transition_to(0);
                        in_main_motor_module = true;
                        in_encoder_module = false;
                        resetMenus();
                        *p_serial
                                << ATERM_CLEAR_SCREEN
                                << ATERM_CURSOR_TO_YX(1, 1) << endl;

                        break;
                    case ('r'):
                        //constant refreshing already
                        transition_to(1)
                        in_imu_module = true;
                        break;
                    default:
                        
                        break;
                    }
            }
            break;
        case (4):
            if (in_imu_module)
            {
                printIMUModuleOptions();
                if (hasUserInput())
                    switch (char_in)
                    {
                    case ('q'):
                        *p_serial << ATERM_CLEAR_SCREEN
                                  << PMS("->Selected: ") << char_in << endl
                                  << endl
                                  << endl
                                  << PMS("\t->Returning to Mission Control.. ")
                                  << endl
                                  << PMS("\t->Releasing IMU..") << endl;
                        transition_to(0);

                        in_imu_module = false;
                        resetMenus();   

                        break;
                        default:
                        break;
                        *p_serial << ATERM_CLEAR_SCREEN;
                    }




                    case ('r'):
                        
                        break;
                    default:
                        break;
                    }
            }
            break;
        // Drive Mode
        case (5):
            if (in_drive_mode)
            {
                printDriveModeOptions();
                // printDashBoard();
                if (hasUserInput())
                    switch (char_in)
                    {
                    case ('q'):
                        *p_serial << ATERM_CLEAR_SCREEN
                                  << PMS("->Selected: ") << char_in << endl
                                  << endl
                                  << endl
                                  << PMS("\t->Returning to Mission Control.. ")
                                  << endl
                                  << PMS("\t->Releasing Drive Mode..") << endl;
                        transition_to(0);
                        in_drive_mode = false;
                        resetMenus();
                        break;
                    case ('s'):
                        *p_serial << endl
                                  << PMS("Input Power Value for Motor: ")
                                  << endl;
                        getNumberInput();
                        setMotor(0, (int16_t)number_entered, SETPOWER);
                        *p_serial
                                << endl << endl
                                << PMS ("\tPower set at ") << number_entered
                                << PMS (". ") << endl << endl
                                << PMS ("Printing DashBoard.. ") << endl
                                << endl;
                        resetMenus();
                        printDashBoard();
                        break;
                    case ('r'):
                        *p_serial
                                << PMS ("Printing DashBoard.. ")
                                << endl
                                << endl;
                        resetMenus();
                        printDashBoard();

                        break;
                    default:
                        break;
                    }
                int16_t x_direction = y_joystick -> get();
                int16_t map_x = x_direction - 526;
                if (x_direction > 526)
                {
                    map_x = 2 * (x_direction - 526);
                }
                else
                {
                    map_x = -2 * (526 - x_direction);
                }

                motor_setpoint -> put(map_x);

                motor_directive -> put(SETPOWER);

                // *p_serial
                //         << ATERM_CURSOR_TO_YX(19, 1)
                //         << ATERM_ERASE_IN_LINE(0)
                //         << gear_state -> get()
                //         << PMS ("\t\t")
                //         << motor_setpoint -> get()
                //         << PMS("\t")
                //         << PMS("\t")
                //         << motor_power -> get()
                //         << PMS("\t")
                //         << PMS("\t")
                //         << encoder_count -> get()
                //         << PMS("\t")
                //         << ATERM_CURSOR_TO_YX(23, 1)
                //         << ATERM_ERASE_IN_LINE(0)
                //         << steering_power -> get()
                //         << PMS("    \t")
                //         << encoder_ticks_per_task -> get()
                //         << PMS("\t")
                //         << PMS("\t")
                //         << x_joystick -> get()
                //         << PMS("\t")
                //         << PMS("\t")
                //         << y_joystick -> get()
                //         << PMS("\t");
                *p_serial << encoder_ticks_per_task -> get() << endl;

            }
            break;
        //JoyStick test
        case (6):
            break;
        default:
            *p_serial << PMS ("Illegal state! Resetting AVR") << endl;
            wdt_enable (WDTO_120MS);
            for (;;);
            break;

        } // End switch state

        runs++;                             // Increment counter for debugging

        // No matter the state, wait for approximately a millisecond before we
        // run the loop again. This gives lower priority tasks a chance to run
        delay_ms (5);
    }
Ejemplo n.º 16
0
void task_brightness::run (void)
{
   // Make a variable which will hold times to use for precise task scheduling
   TickType_t previousTicks = xTaskGetTickCount ();

   // Create an analog to digital converter driver object and a variable in which to
   // store its output. The variable p_my_adc only exists within this run() method,
   // so the A/D converter cannot be used from any other function or method
   adc* p_my_adc = new adc (p_serial);

   //**  CREATE THE MOTOR DRIVERS  **//
   
   // create a pointer to a motor driver object and pass it addresses to PORTC, PORTB, OC1B and Pin Values for PC0, PC2, and PB6 as the PWM
   motor_driver* p_motor1 = new motor_driver(p_serial, &PORTC, &PORTC, &PORTB, &OCR1B, PC0, PC1, PC2, PB6);

   // create a pointer to a motor driver object and pass it addresses to PORTD, PORTB, OC1A and Pin Values for PD5, PD7, and PB5 as the PWM
   motor_driver* p_motor2 = new motor_driver(p_serial, &PORTD, &PORTD, &PORTB, &OCR1A, PD5, PD6, PD7, PB5);




   // Configure counter/timer 3 as a PWM for LED brightness. First set the data
   // direction register so that the pin used for the PWM will be an output. The 
   // pin is Port E pin 4, which is also OC3B (Output Compare B for Timer 3)
   DDRE = (1 << 4);

   // To set 8-bit fast PWM mode we must set bits WGM30 and WGM32, which are in two
   // different registers (ugh). We use COM3B1 and Com3B0 to set up the PWM so that
   // the pin output will have inverted sense, that is, a 0 is on and a 1 is off; 
   // this is needed because the LED connects from Vcc to the pin. 
   TCCR3A |= (1 << WGM30) | (1 << COM3B1) | (1 << COM3B0);

   // The CS31 and CS30 bits set the prescaler for this timer/counter to run the
   // timer at F_CPU / 64
   TCCR3B |= (1 << WGM32) | (1 << CS31)  | (1 << CS30);




   // Configure counter/timer 1 as a PWM for Motor Drivers. 
   // COM1A1/COM1B1 to set to non inverting mode. 
   // WGM10 to set to Fast PWM mode (only half ughhhhh)
   TCCR1A |= (1 << WGM10) | (1 << COM1A1) | (1 << COM1B1);
   // This is the second Timer/Counter Register
   // WGM12 (other half of Fast PWM) 
   // CS11 Sets the presacler to 8 (010)
   TCCR1B |= (1 << WGM12) | (1 << CS11); 

   // This is the task loop for the brightness control task. This loop runs until the
   // power is turned off or something equally dramatic occurs
   for (;;)
   {
      // Read the A/D converter from channel 1
      uint16_t a2d_reading = p_my_adc->read_once(1);

      // Convert the A/D reading into a PWM duty cycle. The A/D reading is between 0
      // and 1023; the duty cycle should be between 0 and 255. Thus, divide by 4
      uint16_t duty_cycle = a2d_reading / 4;
      
      int16_t power = ((int16_t)duty_cycle * 1);
      
      //doesn't let the duty_cycle go to 0 because then the power is 0.
      if(duty_cycle == 0){duty_cycle++;}
      //From 00 - 64 we want to decrease forwards 
      //From 65 - 128 we want to increase backwards
      //From 129 - 192 we want to set both outs to high to set holding brake
      //From 193 - 255 we want to set both outs to low so that they don't affect the motor
      if(duty_cycle <= 64)
      {
         //forwards start from high speed to go to low speed
         power = 255 - (4 * duty_cycle);
        
         p_motor1->set_power(power);
         p_motor2->set_power(duty_cycle);
      }
      else if(duty_cycle > 64 && duty_cycle <= 128)
      {
         //backwards start from low speed to go to high speed
         power = -4 * (duty_cycle - 64);
         p_motor1->set_power(power);
         p_motor2->set_power(-1*duty_cycle);
      }
      else if( duty_cycle > 128 && duty_cycle <= 192)
      {
         //power stopping
         power = 4 * (duty_cycle - 128);
         p_motor1->brake(power);
         p_motor2->brake(power);
      }
      else
      {
         //free wheeling
         p_motor1->brake();
         p_motor2->brake();
      }

      //print the Duty_Cycle in comparison to the Power Signal being pumped into set_power

      *p_serial <<PMS ("Duty_Cycle: ")<< duty_cycle <<dec <<endl
           <<PMS ("Power_Signal: ")<< power <<dec <<endl;


      // Set the brightness. Since the PWM has already been set up, we only need to
      // put a new value into the duty cycle control register, which on an AVR is 
      // the output compare register for a given timer/counter
      OCR3B = duty_cycle;
      
      //OCR1B = duty_cycle;
      // Increment the run counter. This counter belongs to the parent class and can
      // be printed out for debugging purposes
      runs++;

      // This is a method we use to cause a task to make one run through its task
      // loop every N milliseconds and let other tasks run at other times
      delay_from_for_ms (previousTicks, 10);
   }
}
bool hex_receiver::decode (uint16_t char_in)
{
	// If we get a return character, expect that it will be followed by the 
	// beginning of some useful data and reset the decoder
	if ((char_in == '\n') || (char_in == '\r'))
	{
		decoder_state = 0;
	}
	else
	{
		switch (decoder_state)
		{
			// State 0: We haven't received any characters yet; the first one is 
			//          the first character of the type code. Reset everything to
			//          condition at start of reading process
			case (0):
				good_data = false;
				computed_crc = 0xFFFF;
				type_code = ascii_to_nibble (char_in) << 4;
				p_data = NULL;
				decoder_state = 1;
				break;

			// State 1: Get the second nibble of the command code
			case (1):
				type_code |= ascii_to_nibble (char_in);
				decoder_state = 2;
				HXR_DBG (p_serial, hex << PMS ("Code: ") << type_code << endl);

				// OK, we have the code; use it to get a pointer to the object into
				// which we'll be writing the data
				p_map = p_first_map;
				while (p_map != NULL)
				{
					// If debugging, show what we're looking at
					HXR_DBG (p_serial, PMS ("HXR ptr: ") << p_map << endl);

					// If we have a matching code, get the corresponding data pointer
					if (p_map->code == type_code)
					{
						p_data = (uint8_t*)(p_map->p_obj);
						HXR_DBG (p_serial, PMS (" dptr: ") << p_data << endl);
						break;
					}
					else
					{
						HXR_DBG (p_serial, PMS ("HXR ") << hex << p_map->code 
								 << PMS (" != ") << type_code << endl);
					}

					// If no match found, go to the next item in the list
					p_map = p_map->p_next;
				}
				break;

			// State 2: Get the first nibble of the package size
			case (2):
				size = ascii_to_nibble (char_in) << 4;
				decoder_state = 3;
				break;

			// State 3: Get the second nibble of the package size
			case (3):
				size |= ascii_to_nibble (char_in);
				HXR_DBG (p_serial, PMS (" size: ") << size << hex << endl);
				decoder_state = 4;
				break;

			// State 4: Get the first nibble of whatever is next
			case (4):
				num_in = ascii_to_nibble (char_in) << 4;
				decoder_state = 5;
				break;

			// State 5: Get the second nibble of whatever is next. If this isn't 
			//          the last item of data, go back to state 4 for another byte
			case (5):
				num_in |= ascii_to_nibble (char_in);
				if (p_data != NULL)
				{
					HXR_DBG (p_serial, hex << p_data << "<-" << num_in << endl);
					*p_data++ = num_in;
				}

				// Update a cyclic reduncancy check (fancy checksum) for the data
				computed_crc = _crc_ccitt_update (computed_crc, num_in);

				if (--size > 0)
				{
					decoder_state = 4;
				}
				else
				{
					decoder_state = 6;
				}
				break;

			// State 6: Get the first nibble of the checksum
			case (6):
				received_crc = (uint16_t)(ascii_to_nibble (char_in) << 4);
				decoder_state = 7;
				break;

			// State 7: Get the second nibble of the checksum
			case (7):
				received_crc |= ascii_to_nibble (char_in);
				received_crc <<= 4;
				decoder_state = 8;
				break;

			// State 8: Get the third nibble of the checksum
			case (8):
				received_crc |= ascii_to_nibble (char_in);
				received_crc <<= 4;
				decoder_state = 9;
				break;

			// State 9: Get the last nibble of the checksum and check the CRC
			case (9):
				received_crc |= ascii_to_nibble (char_in);
				decoder_state = 0;
				HXR_DBG (p_serial, PMS (":") << received_crc << endl);
				if (received_crc == computed_crc)
				{
					good_data = true;
				}
				else
				{
					HXR_DBG (p_serial, endl << PMS ("Bad CRC:") << hex << received_crc
							 << PMS (",") << computed_crc << dec << endl);
				}
				break;

			// We should never get here. Wait for a return, then reset
			default:
				// Code just before the state machine detects reset characters
				break;
		};
	}

	return (good_data);
}