Пример #1
0
// in an previous version white space was allowed befor the command, but not now.
// a command string always starts at postion 2 and ends at the first white space
// the command looks like an MQTT topic or the directory structure of a file system 
// e.g. /0/pwm 127
// find end of command and place a null termination so it can be used as a string
uint8_t findCommand(void) 
{
    uint8_t lastAlpha =2;
    
    // the command always starts after the addrss at position 2
    command = command_buf + lastAlpha;
    
    // Only an isspace or null may terminate a valid command.
    // The command is made of chars of isalpa, '/', or '?'.
    while( !( isspace(command_buf[lastAlpha]) || (command_buf[lastAlpha] == '\0') ) && lastAlpha < (COMMAND_BUFFER_SIZE-1) ) 
    {
        if ( isalpha(command_buf[lastAlpha]) || (command_buf[lastAlpha] == '/') || (command_buf[lastAlpha] == '?') ) 
        {
            lastAlpha++;
        }
        else
        {
            if (echo_on) printf_P(PSTR("{\"err\": \"BadCharInCmd '%c'\"}\r\n"),command_buf[lastAlpha]);
            initCommandBuffer();
            return 0;
        }
    }
    
    // command does  not fit in buffer
    if ( lastAlpha >= (COMMAND_BUFFER_SIZE-1) ) 
    {
        if (echo_on) printf_P(PSTR("{\"err\": \"HugeCmd\"}\r\n"));
        initCommandBuffer();
        return 0;
    }

    if ( isspace(command_buf[lastAlpha]) )
    {
        // the next poistion may be an argument.
        if ( findArgument(lastAlpha+1) )
        {
            // replace the space with a null so command works as a null terminated string.
            command_buf[lastAlpha] = '\0';
        }
        else
        {
            // isspace() found after command but argument was not valid 
            if (echo_on) printf_P(PSTR("{\"err\": \"CharAftrCmdBad '%c'\"}\r\n"),command_buf[lastAlpha+1]);
            initCommandBuffer();
            return 0;
        }
    }
    else
    {
        if (command_buf[lastAlpha] != '\0')
        {
            // null must end command. 
            if (echo_on) printf_P(PSTR("{\"err\": \"MissNullAftrCmd '%c'\"}\r\n"),command_buf[lastAlpha]);
            initCommandBuffer();
            return 0;
        }
    }
    // zero indexing is also the count and should match with strlen()
    return lastAlpha;
}
Пример #2
0
// pinMode( arg[0], arg[1] )
void Mode(void)
{
    if ( (command_done == 10) )
    {
        // check that arg[0] is a digit 
        if ( ( !( isdigit(arg[0][0]) ) ) )
        {
            printf_P(PSTR("{\"err\":\"pModeNaN\"}\r\n"));
            initCommandBuffer();
            return;
        }
        // and arg[0] value is 2|3|24|25|26|27 
        uint8_t a = atoi(arg[0]);
        if ( (a != 2) && (a != 3) && ( ( a < 24) || (a > 27) ) )
        {
            printf_P(PSTR("{\"err\":\"pModeOutOfRng\"}\r\n"));
            initCommandBuffer();
            return;
        }
        // also arg[1] is not ('INPUT' or 'OUTPUT')
        if ( !( (strcmp_P( arg[1], PSTR("INPUT")) == 0) || (strcmp_P( arg[1], PSTR("OUTPUT")) == 0) ) ) 
        {
            printf_P(PSTR("{\"err\":\"pModeNaMode\"}\r\n"));
            initCommandBuffer();
            return;
        }
        serial_print_started_at = millis();
        if (strcmp_P( arg[1], PSTR("OUTPUT")) == 0 ) 
        {
            pinMode(a, OUTPUT);
        }
        else
        {
            pinMode(a, INPUT);
        }
        
        printf_P(PSTR("{\""));
        command_done = 11;
    }
    else if ( (command_done == 11) )
    {  
        echo_digital_pin_in_json_rply();
        printf_P(PSTR("\":\""));
        command_done = 12;
    }
    else if ( (command_done == 12) )
    {
        printf( arg[1] );
        printf_P(PSTR("\"}\r\n"));
        initCommandBuffer();
    }
    else
    {
        printf_P(PSTR("{\"err\":\"pModeCmdDnWTF\"}\r\n"));
        initCommandBuffer();
    }
}
Пример #3
0
// digitalToggle( arg[0] )
void Toggle(void)
{
    if ( (command_done == 10) )
    {
        // check that arg[0] is a digit 
        if ( ( !( isdigit(arg[0][0]) ) ) )
        {
            printf_P(PSTR("{\"err\":\"dTogNaN\"}\r\n"));
            initCommandBuffer();
            return;
        }
        // and arg[0] value is 2|3|24|25|26|27  
        uint8_t a = atoi(arg[0]);
        if ( (a != 2) && (a != 3) && ( ( a < 24) || (a > 27) ) )
        {
            printf_P(PSTR("{\"err\":\"dTogOutOfRng\"}\r\n"));
            initCommandBuffer();
            return;
        }
        serial_print_started_at = millis();
        digitalToggle(a);
        
        printf_P(PSTR("{\""));
        command_done = 11;
    }
    else if ( (command_done == 11) )
    {  
        echo_digital_pin_in_json_rply();
        printf_P(PSTR("\":\""));
        command_done = 12;
    }
    else if ( (command_done == 12) )
    {
        uint8_t a = atoi(arg[0]);
        if ( (a > (NUM_DIGITAL_PINS-1)) ) // the badPinCheck will barf at compile time without testing the value ... amazing
        {
            return;
        }
        bool pin = digitalRead(a);
        if (pin)
        {
            printf_P(PSTR("HIGH"));
        }
        else
        {
            printf_P(PSTR("LOW"));
        }
        printf_P(PSTR("\"}\r\n"));
        initCommandBuffer();
    }
    else
    {
        printf_P(PSTR("{\"err\":\"dTogCmdDnWTF\"}\r\n"));
        initCommandBuffer();
    }
}
Пример #4
0
void PM3Monitor::reset()
{

	initCommandBuffer();
	
	// Reset
	//
	addCSafeData(CSAFE_GOFINISHED_CMD);
	addCSafeData(CSAFE_GOIDLE_CMD);
	
	
	executeCSafeCommand("go idle tkcmdsetCSAFE_command" );

	initCommandBuffer();
	// Start.
 	addCSafeData(CSAFE_GOHAVEID_CMD);
	addCSafeData(CSAFE_GOINUSE_CMD);
	
	executeCSafeCommand("go in use tkcmdsetCSAFE_command" );

	try 
	{
	}
		
	catch (...) 
	{
		throw;
		//some how this somtimes goes wrong, ignore because it still works fine
		//todo find out why and fix it
	}
	
	initCommandBuffer();
	addCSafeData(CSAFE_RESET_CMD);
	executeCSafeCommand("reset tkcmdsetCSAFE_command" );

	
	
}
Пример #5
0
// assemble command line from incoming char's 
void AssembleCommand(char input) 
{
    // a return or new-line finishes the line (or starts a new command line)
    if ( (input == '\r') || (input == '\n') ) // pressing enter in picocom sends a \r
    {
        //echo both carrage return and newline.
        if (echo_on) printf("\r\n");
        
        // finish command line as a null terminated string
        command_buf[command_head] = '\0';
        
        // do not go past the buffer
        if (command_head < (COMMAND_BUFFER_SIZE - 1) )
        {
            ++command_head;
        }
        else // command is to big 
        {
            if (echo_on) printf_P(PSTR("Ignore_Input\r\n"));
            initCommandBuffer();
        }
        command_done = 1;                     
    }
    else
    {
        //echo the input  
        if (echo_on) printf("%c", input);

        // assemble the command
        command_buf[command_head] = input;
        
        // do not go past the buffer
        if (command_head < (COMMAND_BUFFER_SIZE - 1) )
        {
            ++command_head;
        }
        else // command is to big
        {
            command_buf[1] = '\0'; 
            if (echo_on) printf_P(PSTR("Ignore_Input\r\n"));
            echo_on = 0;
        }
    }
}
Пример #6
0
void PM3Monitor::accumulateForceCurve()
{
    initCommandBuffer();
	
	addCSafeData(CSAFE_SETUSERCFG1_CMD);
	addCSafeData(0x03);
	addCSafeData(CSAFE_PM_GET_FORCEPLOTDATA);
	addCSafeData(0x01);
	addCSafeData(0x20);
	
	// Handle power curve.
	
	uint nPointsReturned = 0xFF;
	
	while (0 < nPointsReturned)
	{  
		// Get any points available and consume them into the array.
		_rsp_data_size = CM_DATA_BUFFER_SIZE;
		
		//clear just in case this may be the problem
		for (int i=0;i<CM_DATA_BUFFER_SIZE;i++)
			_rsp_data[i] =0;	
		
		executeCSafeCommand("accumulateForceCurve tkcmdsetCSAFE_command");
		
		nPointsReturned = _rsp_data[4];
		short unsigned int orgCount = _strokeData.forcePlotCount;
		for (unsigned short int i = 0; i < nPointsReturned; i += 2)
		{  
			_strokeData.forcePlotPoints[_strokeData.forcePlotCount] = _rsp_data[5 + i] + (_rsp_data[6 + i] << 8);
			(_strokeData.forcePlotCount)++;
			if (_strokeData.forcePlotCount>=MAX_PLOT_POINTS)
				throw PM3Exception(ERROR_POINT_BUFFER_OVERFLOW,"Plot point buffer overflow");
			
		}
		if (nPointsReturned>0)
			incrementalPowerCurveUpdate(_strokeData.forcePlotPoints,
										orgCount,
										_strokeData.forcePlotCount);
		
		
	}
}	
Пример #7
0
void setup(void) 
{
    pinMode(STATUS_LED,OUTPUT);
    digitalWrite(STATUS_LED,HIGH);
    
    // Initialize Timers, ADC, and clear bootloader, Arduino does these with init() in wiring.c
    initTimers(); //Timer0 Fast PWM mode, Timer1 & Timer2 Phase Correct PWM mode.
    init_ADC_single_conversion(EXTERNAL_AVCC); // warning AREF must not be connected to anything
    init_uart0_after_bootloader(); // bootloader may have the UART setup

    // put ADC in Auto Trigger mode and fetch an array of channels
    enable_ADC_auto_conversion(BURST_MODE);
    adc_started_at = millis();

    /* Initialize UART, it returns a pointer to FILE so redirect of stdin and stdout works*/
    stdout = stdin = uartstream0_init(BAUD);
    
    /* Initialize I2C, with the internal pull-up 
        note: I2C scan will stop without a pull-up on the bus */
    twi_init(TWI_PULLUP);

    /* Clear and setup the command buffer, (probably not needed at this point) */
    initCommandBuffer();

    // Enable global interrupts to start TIMER0 and UART ISR's
    sei(); 
    
    blink_started_at = millis();
    
    rpu_addr = get_Rpu_address();
    blink_delay = BLINK_DELAY;
    
    // blink fast if a default address from RPU manager not found
    if (rpu_addr == 0)
    {
        rpu_addr = '0';
        blink_delay = BLINK_DELAY/4;
    }
}
Пример #8
0
void PM3Monitor::lowResolutionUpdate()
{   
	int oldforcePlotCount = _strokeData.forcePlotCount-1;
	
	//search for the part where the curve ended (this is where power is low and power is going down  
	unsigned int prefStrokeData=10000;
	for( int i= _strokeData.forcePlotCount-1;i>=(oldforcePlotCount /2);i--) //search from end till the middle
	{	
		if ( (prefStrokeData<15) && //it is low , must be at end of the stroke
			(_strokeData.forcePlotPoints[i] > prefStrokeData )//it is rising again
			)
		{	
			_strokeData.forcePlotCount=i+2; //use the previous one which was less
			break; //found the real end of the stroke
		}
		prefStrokeData=_strokeData.forcePlotPoints[i];
	}
	
	initCommandBuffer();
	
	// Header and number of extension commands.
	
	addCSafeData(CSAFE_SETUSERCFG1_CMD);
	addCSafeData( 0x03);
	
	// Three PM3 extension commands.
	
	addCSafeData(CSAFE_PM_GET_DRAGFACTOR);
	addCSafeData(CSAFE_PM_GET_WORKDISTANCE);
	addCSafeData(CSAFE_PM_GET_WORKTIME);
	
	// Standard commands.
	
	addCSafeData(CSAFE_GETPACE_CMD);
	addCSafeData(CSAFE_GETPOWER_CMD);
	addCSafeData(CSAFE_GETCADENCE_CMD);
	
	executeCSafeCommand("lowResolutionUpdate tkcmdsetCSAFE_command" );
	
    uint currentbyte = 0;
	uint datalength = 0;
	
	if (_rsp_data[currentbyte] == CSAFE_SETUSERCFG1_CMD)
	{
		currentbyte += 2;
	}
	
	if (_rsp_data[currentbyte] == CSAFE_PM_GET_DRAGFACTOR)
	{
		currentbyte++;
		datalength = _rsp_data[currentbyte];
		currentbyte++;
		
		_strokeData.dragFactor = _rsp_data[currentbyte];
		
		currentbyte += datalength;
	}
	
	if (_rsp_data[currentbyte] == CSAFE_PM_GET_WORKDISTANCE)
	{
		currentbyte++;
		datalength = _rsp_data[currentbyte];
		currentbyte++;
		
		uint distanceTemp = (_rsp_data[currentbyte] + (_rsp_data[currentbyte + 1] << 8) + (_rsp_data[currentbyte + 2] << 16) + (_rsp_data[currentbyte + 3] << 24)) / 10;
		//uint fractionTemp = _rsp_data[currentbyte + 4];
		
		_strokeData.workDistance = distanceTemp;
		
		currentbyte += datalength;
	}
	
	if (_rsp_data[currentbyte] == CSAFE_PM_GET_WORKTIME)
	{
		currentbyte++;
		datalength = _rsp_data[currentbyte];
		currentbyte++;
		
		if (datalength == 5)
		{
			uint timeInSeconds = (_rsp_data[currentbyte] + (_rsp_data[currentbyte + 1] << 8) + (_rsp_data[currentbyte + 2] << 16) + (_rsp_data[currentbyte + 3] << 24)) / 100;
			uint fraction = _rsp_data[currentbyte + 4];
			
			_strokeData.workTime = timeInSeconds + (fraction / 100.0);
			_strokeData.workTimehours = timeInSeconds / 3600;
			_strokeData.workTimeminutes = (timeInSeconds / 60) % 60;
			_strokeData.workTimeseconds = timeInSeconds % 60;
		}
		currentbyte += datalength;
	}
	
	if (_rsp_data[currentbyte] == CSAFE_GETPACE_CMD)
	{
		currentbyte++;
		datalength = _rsp_data[currentbyte];
		currentbyte++;
		
		// Pace is in seconds/Km
		
		uint pace = _rsp_data[currentbyte] + (_rsp_data[currentbyte + 1] << 8);
		// get pace in seconds / 500m
		
		double fPace = pace / 2.0;
		// convert it to mins/500m
		
		_strokeData.splitMinutes = floor(fPace / 60);
		_strokeData.splitSeconds = fPace - (_strokeData.splitMinutes * 60);
		
		currentbyte += datalength;
	}
	
	if (_rsp_data[currentbyte] == CSAFE_GETPOWER_CMD)
	{
		currentbyte++;
		datalength = _rsp_data[currentbyte];
		currentbyte++;
		
		_strokeData.power = _rsp_data[currentbyte] + (_rsp_data[currentbyte + 1] << 8);
		
		currentbyte += datalength;
	}
	
	if (_rsp_data[currentbyte] == CSAFE_GETCADENCE_CMD)
	{
		currentbyte++;
		datalength = _rsp_data[currentbyte];
		currentbyte++;
		
		uint currentSPM = _rsp_data[currentbyte];
		
		if ( currentSPM > 0)
		{
			_nSPM += currentSPM;
			_nSPMReads++;
			
			_strokeData.strokesPerMinute = currentSPM;
			_strokeData.strokesPerMinuteAverage = (double)_nSPM / (double)_nSPMReads;
		}
		
		currentbyte += datalength;
	}
	strokeDataUpdate(_strokeData);
	
	//Copy the part which was left out as begining 
	int i2 = 0;
	if (_strokeData.forcePlotCount>=1)
		_strokeData.forcePlotCount-=1;
	for( int i= _strokeData.forcePlotCount;i<oldforcePlotCount;i++) 
	{	
		_strokeData.forcePlotPoints[i2] =_strokeData.forcePlotPoints[i];
		i2++;
	}
	_strokeData.forcePlotCount = i2;

	
}
Пример #9
0
void PM3Monitor::highResolutionUpdate()
{
    _previousStrokePhase = _currentStrokePhase;
	
    initCommandBuffer();
	
	
	// Get the stroke state.
	
	addCSafeData(CSAFE_SETUSERCFG1_CMD);
	addCSafeData(0x01);
	addCSafeData(CSAFE_PM_GET_STROKESTATE);
	
	executeCSafeCommand("highResolutionUpdate tkcmdsetCSAFE_command");
	
	uint currentbyte = 0;
	uint datalength = 0;
	
	if (_rsp_data[currentbyte] == CSAFE_SETUSERCFG1_CMD)
	{
		currentbyte += 2;
	}
	
	if (_rsp_data[currentbyte] == CSAFE_PM_GET_STROKESTATE)
	{
		currentbyte++;
		datalength = _rsp_data[currentbyte];
		currentbyte++;
		
		switch (_rsp_data[currentbyte])
		{
			case 0:
			case 1:
				_currentStrokePhase = StrokePhase_Catch;
				break;
			case 2:
				_currentStrokePhase = StrokePhase_Drive;
				break;
			case 3:
				_currentStrokePhase = StrokePhase_Dwell;
				break;
			case 4:
				_currentStrokePhase = StrokePhase_Recovery;
				break;
		}
		currentbyte += datalength;
	}
	
	// Get any force curve points available.
	
	
	accumulateForceCurve();
	
	if (_currentStrokePhase != _previousStrokePhase)
	{
		// If this is the dwell, complete the power curve.
		//if (_previousStrokePhase == StrokePhase_Drive)
		if (_currentStrokePhase == StrokePhase_Recovery)
		{   
		    lowResolutionUpdate();						
		}
		
		// Update the stroke phase.
		newStrokePhase(_currentStrokePhase);
	}
}
Пример #10
0
Файл: ht.c Проект: epccs/RPUno
/* Return RH and Temp using ICP1 capture, also return PV_IN (solar input voltage) and PWR (battery voltage). */
void Ht(void)
{
    // only works if both edges are tracked and prescaler is set to CPU clock.
    if ( (icp1_edge_mode != TRACK_BOTH) || ( (TCCR1B & 0x07) != 0x01) )
    {
        printf_P(PSTR("{\"err\":\"IcpWrongMode\"}\r\n"));
        initCommandBuffer();
        return;
    }
    if ( (command_done == 10) )
    {
        event_pair = 15;

        if ((event_pair < 1) || (event_pair >= (ICP_EVENT_BUFF_SIZE/2)) )
        {
            printf_P(PSTR("{\"err\":\"IcpMaxArg%d\"}\r\n"),(ICP_EVENT_BUFF_SIZE/2)-1);
            initCommandBuffer();
        }
        else
        {
            // event_pair should have a valid value for how many high-low capture pairs to print, but I need a counter to track up to it.
            event_pair_output =0;
            
            // buffer has enough readings
            if (icp1.count > ((event_pair * 2) +1) ) 
            { 
                uint8_t num_of_events_needed=((event_pair * 2) +1);
                
                // copy from icp1 to icp1_db
                double_buffer_copy(&icp1, &icp1_db, num_of_events_needed);
                
                // used to delay serial printing
                serial_print_started_at = millis();
                
                command_done = 11;
            }
            else
            {
                printf_P(PSTR("{\"err\":\"IcpEvntCnt@%d\"}\r\n"), icp1.count);
                initCommandBuffer();
            }
        }
    }
    
    else if ( (command_done == 11) )
    { // use the event_count for indexing the time stamps
        sample_size = 0;
        low_sum = 0;
        high_sum = 0;
        printf_P(PSTR("{\"count\":\"%lu\","),icp1_db.count );
        command_done = 12;
    }

    else if ( (command_done == 12) )
    {
        // cast to int to use two's complement math then cast back into a uint8_t and mask to the buffer size.
        uint8_t high2low_event_index = ((uint8_t)(((int8_t)icp1_db.head) - ((int8_t)2*(event_pair_output)))) & (ICP_EVENT_BUFF_MASK);
        uint8_t low2high_event_index = ((uint8_t)(((int8_t)high2low_event_index) - 1)) & (ICP_EVENT_BUFF_MASK);
        uint8_t period_event_index = ((uint8_t)(((int8_t)low2high_event_index) - 1)) & (ICP_EVENT_BUFF_MASK);

        // the event time is keep in two byte arrays to make the ISR fast and 
        // allow up to 32 events with quick access of the AVR ldd instruction.
        uint16_t high2low_event;
        uint16_t low2high_event;
        uint16_t period_event;
        high2low_event = (((uint16_t)icp1_db.event.Byt1[high2low_event_index]) <<8) + ((uint16_t)icp1_db.event.Byt0[high2low_event_index]);
        low2high_event = (((uint16_t)icp1_db.event.Byt1[low2high_event_index]) <<8) + ((uint16_t)icp1_db.event.Byt0[low2high_event_index]);
        period_event = (((uint16_t)icp1_db.event.Byt1[period_event_index]) <<8) + ((uint16_t)icp1_db.event.Byt0[period_event_index]);

        // Now find counts between events while ICP1 was low and then when it was high
        // cast to int causes two's complement math to be used which gives correct result through a roll over
        low = (uint16_t)((int16_t)high2low_event - (int16_t)low2high_event);
        high = (uint16_t)((int16_t)low2high_event - (int16_t)period_event);
        
        // if the last capture was on a falling event, swap low and high count
        if ( (icp1_db.event.status[high2low_event_index] & (1<<RISING)) == 0)
        { 
            uint16_t temp = low;
            low = high;
            high = temp;
        }
        
        // the high and low timer counts are times between events
        // When HT is hot the high count can be less than 300 which may have some 
        // skipping. This is due to the other ISR's running and not letting the capture  
        // ISR do its job fast enough. A skip will cause the high count to be larger than the low.
        if ( high < low ) // this will not work bellow about -30C or -22F
        {
            sample_size += 1;
            low_sum += low;
            high_sum += high;
        }
        
        if ( (++event_pair_output) >= event_pair) 
        {
            command_done = 13;
        }
        else
        {
            command_done = 12;
        }
    }
    
    else if ( (command_done == 13) )
    {
        printf_P(PSTR("\"smpl_sz\":\"%u\""),(unsigned int)sample_size);
        if (sample_size > 10)
        {
            printf_P(PSTR(","));
            command_done = 14;
        }
        else
        {
            command_done = 24;
        }
        
    }

    else if ( (command_done == 14) )
    {
        // a fixed 1% resistor that discharges the timing capacitor, it does not very with temperature
        float R7 = 1500000.0;
        
        //R9 (an NTC thermistor) is measured from ratio of its charge rate and the R7 discharge rate
        float R9 = R7 * high_sum/low_sum;
        
        // Room Temp in K
        float RoomTemp = 25.0 + 273.15;
        
        // R9 is an NTC with Bata(K) 4582
        float Beta = 4582.0;
        
        //R9 at RoomTemp (the actual value is within 5% of this)
        float R9rt = 470000.0;
        
        //sensor Temp in K
        sensor_temp = ((RoomTemp)*Beta/log(R9rt/R9))/(Beta/log(R9rt/R9)-RoomTemp);
        
        // print in deg F
        printf_P(PSTR("\"deg_f\":\"%1.2f\","),(sensor_temp - 273.15)*9/5 + 32);
        command_done = 15;
    }
    
    else if ( (command_done == 15) )
    {
        // a fixed 1% resistor that discharges the timing capacitor, it does not very with temperature
        float R7 = 1500000.0;
        
        // Room Temp in K
        float RoomTemp = 25.0 + 273.15;
        
        // 555 IC supply
        float V555 = 3.58;
        
        // the voltage over which the ramp time occures, which is 1/3 of the 555 IC supply
        float V = V555/3;
        
        // see Robert A. Pease "What's All This VBE Stuff, Anyhow?"
        float Vbe = 0.675 - (0.00175 *(sensor_temp - RoomTemp) );
        
        // the discharge current is mirrored from a 1.5Meg resistor (it is about 2uA at room temp)
        float i = (V555-Vbe)/R7;
        
        // sensor capacatance
        float C = i * (1.0/F_CPU) * low_sum/(sample_size*V);
        
        // C@55%RH, note I think the circuit adds to this e.g. 5pf or more.
        float  Crt = 180.0*1E-12;
        
        // ratio used for reverse polynomial response of HS1101LF
        float X = C/Crt;
        
        // reverse polynomial response of HS1101LF from datasheet
        float RH = (-3.4656*1E3*X*X*X) + (1.0732*1E4*X*X) + (-1.0457*1E4*X) + (3.2459*1E3);
        
        printf_P(PSTR("\"%%RH\":\"%1.2f\","),RH);
        command_done = 16;
    }
    
    // The ADC values are from 0 to 1023 for 1024 slots where each reperesents 1/1024 of the reference. Last slot has issues
    // https://forum.arduino.cc/index.php?topic=303189.0    
    else if ( (command_done == 16) )
    {
        // analog channel 6 is connected to the solar power input (PV_IN)
        float PV_IN = analogRead(6)*(5.0/1024.0)*(532.0/100.0);
        printf_P(PSTR("\"PV_IN\":\"%1.2f\""),PV_IN);
        command_done = 17;
    }

    else if ( (command_done == 17) )
    {
        // analog channel 7 is connected to the battery power (PWR)
        float PWR = analogRead(7)*(5.0/1024.0)*(3.0/2.0);
        printf_P(PSTR("\"PWR\":\"%1.2f\""),PWR);
        command_done = 24;
    }
    
    else if ( (command_done == 24) )
    {
        printf_P(PSTR("}\r\n"));
        command_done = 25;
    }
    
    else if ( (command_done == 25) )
    { // delay between JSON printing
        unsigned long kRuntime= millis() - serial_print_started_at;
        if ((kRuntime) > ((unsigned long)SERIAL_PRINT_DELAY_MILSEC))
        {
            command_done = 10; /* This keeps looping the output forever (until a Rx char anyway) */
        }
    }
    else
    {
        printf_P(PSTR("{\"err\":\"IcpCmdDoneWTF\"}\r\n"));
        initCommandBuffer();
    }
}
Пример #11
0
Файл: main.c Проект: epccs/RPUno
int main(void) {    

    /* Initialize UART, it returns a pointer to FILE so redirect of stdin and stdout works*/
    stdout = stdin = uartstream0_init(BAUD);
    
    /* Initialize I2C, with the internal pull-up*/
    twi_init(1);

    /* Clear and setup the command buffer, (probably not needed at this point) */
    initCommandBuffer();
       
    sei(); // Enable global interrupts

    char rpu_addr = get_Rpu_address();
    
    // set a default address if RPU manager not found
    if (rpu_addr == 0)
    {
        rpu_addr = '0';
    }
    
    while(1) 
    {
        // check if character is available to assemble a command, e.g. non-blocking
        if ( (!command_done) && uart0_available() ) // command_done is an extern from parse.h
        {
            // get a character from stdin and use it to assemble a command
            AssembleCommand(getchar());

            // address is a char e.g. the ascii value for '0' warning: a null will terminate the command string. 
            StartEchoWhenAddressed(rpu_addr);
        }
        
        // check if the character is available, and if so stop transmit and the command in process.
        // a multi-drop bus can have another device start transmitting after the second received byte so
        // there is little time to detect a possible collision
        if ( command_done && uart0_available() )
        {
            // dump the transmit buffer to limit a collision 
            uart0_flush(); 
            initCommandBuffer();
        }
        
        // finish echo of the command line befor starting a reply (or the next part of reply)
        if ( command_done && (uart0_availableForWrite() == UART_TX0_BUFFER_SIZE) )
        {
            if ( !echo_on  )
            { // this happons when the address did not match
                initCommandBuffer();
            }
            else
            {
                // command is a pointer to string and arg[] is an array of pointers to strings
                // use findCommand to make them point to the correct places in the command line
                // this can only be done once, since spaces and delimeters are replaced with null termination
                if (command_done == 1)  
                {
                    findCommand();
                    command_done = 10;
                }
                
                if ( (command_done >= 10) && (command_done < 250) )
                {
                     ProcessCmd();
                }
                else 
                {
                    initCommandBuffer();
                }
            }
         }
    }        
    return 0;
}
Пример #12
0
/* return adc values */
void Analog(void)
{
    if ( (command_done == 10) )
    {
        // check that arguments are digit in the range 0..7
        for (adc_arg_index=0; adc_arg_index < arg_count; adc_arg_index++) 
        {
            if ( ( !( isdigit(arg[adc_arg_index][0]) ) ) || (atoi(arg[adc_arg_index]) < 0) || (atoi(arg[adc_arg_index]) > ADC_CHANNELS) )
            {
                printf_P(PSTR("{\"err\":\"AdcChOutOfRng\"}\r\n"));
                initCommandBuffer();
                return;
            }
        }
        // print in steps otherwise the serial buffer will fill and block the program from running
        serial_print_started_at = millis();
        printf_P(PSTR("{"));
        adc_arg_index= 0;
        command_done = 11;
    }
    else if ( (command_done == 11) )
    { // use the channel as an index in the JSON reply
        uint8_t arg_indx_channel =atoi(arg[adc_arg_index]);
        
        if (arg_indx_channel == 0)
        {
            printf_P(PSTR("\"ADC%s\":"),arg[adc_arg_index]);
        }

        if (arg_indx_channel == PV_I) //ADC1
        {
            printf_P(PSTR("\"PV_A\":"));
        }
        
        if (arg_indx_channel == CHRG_I) //ADC2
        {
            printf_P(PSTR("\"CHRG_A\":"));
        }

        if (arg_indx_channel == DISCHRG_I) //ADC3
        {
            printf_P(PSTR("\"DISCHRG_A\":"));
        }

        if (arg_indx_channel == 4)
        {
            printf_P(PSTR("\"ADC4\":"));
        }

        if (arg_indx_channel == 5)
        {
            printf_P(PSTR("\"ADC5\":"));
        }

        if (arg_indx_channel == PV_V) //ADC6
        {
            printf_P(PSTR("\"PV_V\":"));
        }
        
        if (arg_indx_channel == PWR_V) //ADC7
        {
            printf_P(PSTR("\"PWR_V\":"));
        }
        command_done = 12;
    }
    else if ( (command_done == 12) )
    {
        uint8_t arg_indx_channel =atoi(arg[adc_arg_index]);

        // There are values from 0 to 1023 for 1024 slots where each reperesents 1/1024 of the reference. Last slot has issues
        // https://forum.arduino.cc/index.php?topic=303189.0        
        if (arg_indx_channel == 0)
        {
            printf_P(PSTR("\"%1.2f\""),(analogRead(0)*5.0/1024.0));
        }

        if (arg_indx_channel == PV_I) //CCtest board current sense that can be connected to ADC1.
        {
            printf_P(PSTR("\"%1.3f\""),(analogRead(PV_I)*(5.0/1024.0)/(0.068*50.0)));
        }

        if (arg_indx_channel == CHRG_I) // RPUno has ADC2 connected to high side current sense to measure battery charging.
        {
            printf_P(PSTR("\"%1.3f\""),(analogRead(CHRG_I)*(5.0/1024.0)/(0.068*50.0)));
        }

        if (arg_indx_channel == DISCHRG_I) // RPUno has ADC3 connected to high side current sense to measure battery discharg.
        {
            printf_P(PSTR("\"%1.3f\""),(analogRead(DISCHRG_I)*(5.0/1024.0)/(0.068*50.0)));
        }

        if (arg_indx_channel == 4) // RPUno has ADC4 is used for I2C SDA function
        {
            printf_P(PSTR("\"SDA\""));
        }

        if (arg_indx_channel == 5) // RPUno has ADC5 is used for I2C SCL function
        {
            printf_P(PSTR("\"SCL\""));
        }

        if (arg_indx_channel == PV_V) // RPUno has ADC6 connected to a voltage divider from the solar input.
        {
            printf_P(PSTR("\"%1.2f\""),(analogRead(PV_V)*(5.0/1024.0)*(532.0/100.0)));
        }

        if (arg_indx_channel == PWR_V) // RPUno has ADC7 connected a voltage divider from the battery (PWR).
        {
            printf_P(PSTR("\"%1.2f\""),(analogRead(PWR_V)*(5.0/1024.0)*(3.0/2.0)));
        }

        if ( (adc_arg_index+1) >= arg_count) 
        {
            printf_P(PSTR("}\r\n"));
            // initCommandBuffer(); /* This stops the output after one loop*/
            command_done = 13;
        }
        else
        {
            printf_P(PSTR(","));
            adc_arg_index++;
            command_done = 11;
        }
    }
    else if ( (command_done == 13) ) 
    { // delay between JSON printing
        unsigned long kRuntime= millis() - serial_print_started_at;
        if ((kRuntime) > ((unsigned long)SERIAL_PRINT_DELAY_MILSEC))
        {
            command_done = 10; /* This keeps looping output forever (until a Rx char anyway) */
        }
    }
    else
    {
        printf_P(PSTR("{\"err\":\"AdcCmdDoneWTF\"}\r\n"));
        initCommandBuffer();
    }
}
Пример #13
0
int main(void) 
{
    setup();

    while(1) 
    { 
        // use LED to show if I2C has a bus manager
        blink();
        
        // check if character is available to assemble a command, e.g. non-blocking
        if ( (!command_done) && uart0_available() ) // command_done is an extern from parse.h
        {
            // get a character from stdin and use it to assemble a command
            AssembleCommand(getchar());

            // address is an ascii value, warning: a null address would terminate the command string. 
            StartEchoWhenAddressed(rpu_addr);
        }
        
        // check if a character is available, and if so flush transmit buffer and nuke the command in process.
        // A multi-drop bus can have another device start transmitting after getting an address byte so
        // the first byte is used as a warning, it is the onlly chance to detect a possible collision.
        if ( command_done && uart0_available() )
        {
            // dump the transmit buffer to limit a collision 
            uart0_flush(); 
            initCommandBuffer();
        }
        
        // delay between ADC burst
        adc_burst();
          
        // finish echo of the command line befor starting a reply (or the next part of a reply)
        if ( command_done && (uart0_availableForWrite() == UART_TX0_BUFFER_SIZE) )
        {
            if ( !echo_on  )
            { // this happons when the address did not match 
                initCommandBuffer();
            }
            else
            {
                if (command_done == 1)  
                {
                    findCommand();
                    command_done = 10;
                }
                
                // do not overfill the serial buffer since that blocks looping, e.g. process a command in 32 byte chunks
                if ( (command_done >= 10) && (command_done < 250) )
                {
                     ProcessCmd();
                }
                else 
                {
                    initCommandBuffer();
                }
            }
         }
    }        
    return 0;
}
Пример #14
0
/* run reflow profile */
void Reflow(void)
{

    if ( (command_done == 10) )
    {
        eeprom_offset = 0;
        pwm =0;
        last_pwm =0;
        reflow_zone_started_at = millis();
        
        pinMode(SSR, OUTPUT);
        digitalWrite(SSR, LOW);
        
        pinMode(BUZZER, OUTPUT);
        digitalWrite(BUZZER, LOW);

        command_done = 11;
    }
    
    else if ( (command_done == 11) )
    { 
        pwm = eeprom_read_byte( (uint8_t *) (eeprom_offset) ); 
        printf_P(PSTR("{\"millis\":\"%lu\","),reflow_zone_started_at);
        
        // Turn on the SSR if pwm is between 1 thru 254 (255 is used for the buzzer)
        if ( (pwm > 0) && (pwm < 255) )
        {
            digitalWrite(SSR, HIGH);
        }
        if (pwm == 255)
        {
            digitalWrite(BUZZER, HIGH);
        }
        command_done = 12;
    }

    else if ( (command_done == 12) )
    {
        unsigned long now = millis();
        unsigned long kRuntime= now - reflow_zone_started_at;
        if (  (kRuntime) > ( (unsigned long)( 0.5 + (pwm/255.0)*REFLOW_ZONE_DELAY_MILSEC) )  )
        {
            digitalWrite(BUZZER, LOW);
            digitalWrite(SSR, LOW);
            printf_P(PSTR("\"pwm\":\"%u\","),pwm);
            command_done = 13;
        }
        else
        {
            command_done = 12;
        }
    }

    else if ( (command_done == 13) )
    {
        // analog channel 0 may be connected to the Fluke 80TK Thermocouple Module set in deg F output
        float Thermocouple = analogRead(0)*1.0; // (1.1/1023.0)*(1000.0);
        printf_P(PSTR("\"deg_c\":\"%1.2f\""),(Thermocouple -32.0) * (5.0/9.0) );
        command_done = 24;
    }
    
    else if ( (command_done == 24) )
    {
        printf_P(PSTR("}\r\n"));
        command_done = 25;
    }
    
    else if ( (command_done == 25) )
    { 
        unsigned long now = millis();
        unsigned long kRuntime= now - reflow_zone_started_at;
        if ((kRuntime) > ((unsigned long)REFLOW_ZONE_DELAY_MILSEC))
        {
            if (eeprom_offset < EEPROM_SIZE) 
            {
                if ( (pwm == 255) && (last_pwm == 255) )
                {
                    // two consecutive buzzer valuses terminate the profile.
                    initCommandBuffer();
                }
                else
                {
                    eeprom_offset++;
                    last_pwm = pwm;
                    reflow_zone_started_at += REFLOW_ZONE_DELAY_MILSEC; /* advance start time an exact amount*/
                    command_done = 11; /* loop through all eeprom values */
                }
            }
            else
            {
                initCommandBuffer();
            }
        }
    }
    
    else
    {
        printf_P(PSTR("{\"err\":\"ReflowCmdWTF\"}\r\n"));
        initCommandBuffer();
    }
}
Пример #15
0
Файл: main.c Проект: epccs/RPUno
int main(void) {    

    /* Initialize UART, it returns a pointer to FILE so redirect of stdin and stdout works*/
    stdout = stdin = uartstream0_init(BAUD);
    initCommandBuffer();
       
    sei(); // Enable global interrupts starts the UART
    
    // non-blocking code in loop
    while(1) 
    {
        // check if character is available to assemble a command, e.g. non-blocking
        if ( (!command_done) && uart0_available() ) // command_done is an extern from parse.h
        {
            // get a character from stdin and use it to assemble a command
            AssembleCommand(getchar());

            // address is the ascii value for '0' note: a null address will terminate the command string. 
            StartEchoWhenAddressed('0');
        }
        
        // check if the character is available, and if so stop transmit and the command in process.
        // a multi-drop bus can have another device start transmitting after the second received byte so
        // there is little time to detect a possible collision
        if ( command_done && uart0_available() )
        {
            // dump the transmit buffer to limit a collision 
            uart0_flush(); 
            initCommandBuffer();
        }
        
        // finish echo of the command line befor starting a reply (or the next part of reply), also non-blocking.
        if ( command_done && (uart0_availableForWrite() == UART_TX0_BUFFER_SIZE) )
        {
            if ( !echo_on  )
            { // this happons when the address did not match
                initCommandBuffer();
            }
            else
            {
                // command is a pointer to string and arg[] is an array of pointers to strings
                // use findCommand to make them point to the correct places in the command line
                // this can only be done once, since spaces and delimeters are replaced with null termination
                if (command_done == 1)  
                {
                    findCommand();
                    command_done = 2;
                }
                if (command_done == 2)
                {
                    if (command != '\0' )
                    {
                        printf_P(PSTR("{\"cmd\": \"%s\"}\r\n"),command);
                        command_done = 3;
                    }
                    else
                    {
                        initCommandBuffer();
                    }
                }
                if (command_done == 3)
                {
                    printf_P(PSTR("{\"arg_count\": \"%d\"}\r\n"),arg_count);
                    if (arg_count > 0)
                    {
                        command_done = 4;
                    }
                    else
                    {
                        initCommandBuffer();
                    }
                }
                if (command_done == 4)
                {
                    printf_P(PSTR("{\"arg[0]\": \"%s\"}\r\n"),arg[0]);
                    if (arg_count > 1)
                    {
                        command_done = 5;
                    }
                    else
                    {
                        initCommandBuffer();
                    }
                }
                if (command_done == 5)
                {
                    printf_P(PSTR("{\"arg[1]\": \"%s\"}\r\n"),arg[1]);
                    if (arg_count > 2)
                    {
                        command_done = 6;
                    }
                    else
                    {
                        initCommandBuffer();
                    }
                }
                if (command_done == 6)
                {
                    printf_P(PSTR("{\"arg[2]\": \"%s\"}\r\n"),arg[2]);
                    if (arg_count > 3)
                    {
                        command_done = 7;
                    }
                    else
                    {
                        initCommandBuffer();
                    }
                }
                if (command_done == 7)
                {
                    printf_P(PSTR("{\"arg[3]\": \"%s\"}\r\n"),arg[3]);
                    if (arg_count > 4)
                    {
                        command_done = 8;
                    }
                    else
                    {
                        initCommandBuffer();
                    }
                }
                if (command_done == 8)
                {
                    printf_P(PSTR("{\"arg[4]\": \"%s\"}\r\n"),arg[4]);
                    initCommandBuffer();
                }
            }
         }
    }        
    return 0;
}
Пример #16
0
Файл: main.c Проект: epccs/RPUno
int main(void) 
{
    // Initialize Timers, ADC, and clear bootloader, Arduino does these with init() in wiring.c 
    initTimers(); //Timer0 Fast PWM mode, Timer1 & Timer2 Phase Correct PWM mode.
    init_ADC_single_conversion(EXTERNAL_AVCC); // warning AREF should only have a bypass cap
    init_uart0_after_bootloader(); // bootloader may have the UART setup
    
    // setup()

    // Set digital pins to control load
    init_load();

    // Set digital pins to control solar
    init_pv();

    // put ADC in free running Auto Trigger mode
    enable_ADC_auto_conversion(FREE_RUNNING);
    
    
    /* Initialize UART, it returns a pointer to FILE so redirect of stdin and stdout works*/
    stdout = stdin = uartstream0_init(BAUD);
    
    /* Clear and setup the command buffer, (probably not needed at this point) */
    initCommandBuffer();

    sei(); // Enable global interrupts starts TIMER0, UART0, ADC and any other ISR's
    
    // this start up command should run cctest, e.g. after a reset.
    if (uart0_available() == 0)
    {
        strcpy_P(command_buf, PSTR("/0/cctest?"));
        command_done = 1;
        echo_on = 1;
        printf_P(PSTR("%s\r\n"), command_buf);
    }
    
    // loop() 
    while(1) /* I am tyring to use non-blocking code */
    { 
        // check if character is available to assemble a command, e.g. non-blocking
        if ( (!command_done) && uart0_available() ) // command_done is an extern from parse.h
        {
            // get a character from stdin and use it to assemble a command
            AssembleCommand(getchar());

            // address is the ascii value for '0' note: a null address will terminate the command string. 
            StartEchoWhenAddressed('0');
        }
        
        // check if a character is available, and if so flush transmit buffer and nuke the command in process.
        // A multi-drop bus can have another device start transmitting after getting an address byte so
        // the first byte is used as a warning, it is the onlly chance to detect a possible collision.
        if ( command_done && uart0_available() )
        {
            // dump the transmit buffer to limit a collision 
            uart0_flush(); 
            initCommandBuffer();
            
            //Enable the LT3652, which may have been turned off
            digitalWrite(SHUTDOWN, LOW);
            
            // trun off the load
            load_step(0);
        }
        
        // finish echo of the command line befor starting a reply (or the next part of a reply)
        if ( command_done && (uart0_availableForWrite() == UART_TX0_BUFFER_SIZE) )
        {
            if ( !echo_on  )
            { // this happons when the address did not match 
                initCommandBuffer();
            }
            else
            {
                if (command_done == 1)  
                {
                    findCommand();
                    command_done = 10;
                }
                
                // do not overfill the serial buffer since that blocks looping, e.g. process a command in 32 byte chunks
                if ( (command_done >= 10) && (command_done < 250) )
                {
                     ProcessCmd();
                }
                else 
                {
                    initCommandBuffer();
                }
            }
         }
    }        
    return 0;
}
Пример #17
0
// find argument(s) starting from a given offset
uint8_t findArgument(uint8_t at_command_buf_offset) 
{
    if (at_command_buf_offset < COMMAND_BUFFER_SIZE) 
    {
        uint8_t lastAlphaNum = at_command_buf_offset;
        
        //get past any white space, but not end of line (EOL was replaced with a null)
        while (isspace(command_buf[lastAlphaNum]) && !(command_buf[lastAlphaNum] == '\0')) 
        { 
            lastAlphaNum++;
        }

        // after command+space but the char is null
        if( (command_buf[lastAlphaNum] == '\0') ) 
        {
            if (echo_on) printf_P(PSTR("{\"err\": \"NullArgAftrCmd+Sp\"}\r\n"));
            initCommandBuffer();
            return 0;
        }
        
        //for each valid argument add it to the arg array of strings
        for (arg_count = 0; command_buf[lastAlphaNum] != '\0' ; arg_count++) 
        {
            // to many arguments
            if( !(arg_count < MAX_ARGUMENT_COUNT) ) 
            {
                if (echo_on) printf_P(PSTR("{\"err\": \"ArgCnt%dAt%d\"}\r\n"), arg_count, lastAlphaNum);
                initCommandBuffer();
                return 0;
            }   
            
            arg[arg_count] = command_buf + lastAlphaNum;
            
            //  skip through the argument
            while( (isalnum(command_buf[lastAlphaNum]) || (command_buf[lastAlphaNum] == '-')) && (lastAlphaNum < (COMMAND_BUFFER_SIZE-1)) ) 
            { 
                lastAlphaNum++;
            }
            if ( (command_buf[lastAlphaNum] == ARGUMNT_DELIMITER) )
            {
                if ( lastAlphaNum < (COMMAND_BUFFER_SIZE-2) ) 
                {
                    // check if char after delimiter is valid for an arg 
                    if( !(isalnum(command_buf[lastAlphaNum+1]) || (command_buf[lastAlphaNum+1] == '-')) ) 
                    {
                        if (echo_on) printf_P(PSTR("{\"err\": \"ArgAftr'%c@%d!Valid\"}\r\n"),command_buf[lastAlphaNum],lastAlphaNum);
                        initCommandBuffer();
                        return 0;
                    }  
                    
                    // null terminate the argument, e.g. replace the delimiter
                    command_buf[lastAlphaNum] = '\0';
                    lastAlphaNum++;
                }
                else
                {
                    // a delimiter was found but there is not enough room for an argument and null termination
                    if (echo_on) printf_P(PSTR("{\"err\": \"DropArgCmdLn2Lng\"}\r\n"));
                    initCommandBuffer();
                    return 0;
                }
            }
            
            // only EOL or delimiter is valid way to terminate an argument (e.g. a space befor end of line is not valid)
            else if (command_buf[lastAlphaNum] != '\0')
            {
                // do not index past command buffer
                if (echo_on) printf_P(PSTR("{\"err\": \"!DelimAftrArg'%c@%d\"}\r\n"), command_buf[lastAlphaNum],lastAlphaNum);
                initCommandBuffer();
                return 0;
            }
        }
        return arg_count;
    }
    else
    {
        // do not index past command buffer
        if (echo_on) printf_P(PSTR("{\"err\": \"ArgIndxPastCmdBuf\"}\r\n"));
        initCommandBuffer();
        return 0;
    }
}