/* ======================================================================
Function: decode_lux
Purpose : print the lux value
Input   : lux (*10)
          index of sensor number (0 to 3)
====================================================================== */
char * decode_lux(uint16_t lux, char * index)
{
  sprintf_P(pbuf, PSTR("\"lux%s\":"), index);
  #ifdef ARDUINO
    dtostrf(lux/10.0f, 3, 1,  pbuf+strlen(pbuf));
  #else
    ftoa(lux/10.0f, pbuf+strlen(pbuf), 1 );
  #endif
  return pbuf;
}
/* ======================================================================
Function: decode_hum
Purpose : print the humidity
Input   : humidity (*10)
          index of sensor number (0 to 3)
====================================================================== */
char * decode_hum(uint16_t hum, char * index)
{
  sprintf_P(pbuf, PSTR("\"hum%s\":"), index);
  #ifdef ARDUINO
    dtostrf(hum/10.0f, 4, 1,  pbuf+strlen(pbuf));
  #else
    ftoa(hum/10.0f, pbuf+strlen(pbuf), 1 );
  #endif
  return pbuf;
}
示例#3
0
uint8_t EC_Error(void)
{
#ifndef USE_RS485
	ec_client.stop();
#endif
	// add the two error code to the param_readings
	//sprintf(&param_readings[strlen(param_readings)], ",%u,%u", ec_state, mb_state);
	sprintf_P(&param_readings[strlen(param_readings)], PSTR(",,"));  // add blank values - avoid distorted plotting
	return ec_state;
}
示例#4
0
void Display::DisplayBlockTemp() {
  char buf[16];
  char floatStr[16];
  
  sprintFloat(floatStr, GetThermocycler().GetPlateTemp(), 1, true);
  sprintf_P(buf, BLOCK_TEMP_FORM_STR, floatStr);
 
  iLcd.setCursor(13, 0);
  iLcd.print(buf);
}
示例#5
0
void widget_avg_vario_draw(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t flags)
{
	uint8_t lh = widget_label_P(PSTR("Avg"), x, y);

	float val = fc.avg_vario;

	if (config.vario.flags & VARIO_UNITS_I)
		val *= FC_MPS_TO_100FPM;

	if (abs(val) < 0.09)
		val = 0;

	char text[10];
	if (fc.baro_valid)
		sprintf_P(text, PSTR("%0.1f"), val);
	else
		sprintf_P(text, PSTR("-.-"), val);
	widget_value_int(text, x, y + lh, w, h - lh);
}
示例#6
0
bool save() {
    uint8_t year;
    uint8_t month;
    uint8_t day;
    if (datetime::getDate(year, month, day)) {
        sprintf_P(channel->cal_conf.calibration_date, PSTR("%d%02d%02d"), (int)(2000 + year), (int)month, (int)day);
    }
    else {
        strcpy(channel->cal_conf.calibration_date, "");
    }

    memset(&channel->cal_conf.calibration_remark, 0, sizeof(channel->cal_conf.calibration_remark));
    strcpy(channel->cal_conf.calibration_remark, remark);

    if (voltage.min_set && voltage.mid_set && voltage.max_set) {
        channel->cal_conf.flags.u_cal_params_exists = 1;

        channel->cal_conf.u.min.dac = channel->U_CAL_VAL_MIN;
        channel->cal_conf.u.min.val = voltage.min;
        channel->cal_conf.u.min.adc = voltage.min_adc;

        channel->cal_conf.u.mid.dac = channel->U_CAL_VAL_MID;
        channel->cal_conf.u.mid.val = voltage.mid;
        channel->cal_conf.u.mid.adc = voltage.mid_adc;

        channel->cal_conf.u.max.dac = channel->U_CAL_VAL_MAX;
        channel->cal_conf.u.max.val = voltage.max;
        channel->cal_conf.u.max.adc = voltage.max_adc;

        voltage.level = LEVEL_NONE;
    }

    if (current.min_set && current.mid_set && current.max_set) {
        channel->cal_conf.flags.i_cal_params_exists = 1;

        channel->cal_conf.i.min.dac = channel->I_CAL_VAL_MIN;
        channel->cal_conf.i.min.val = current.min;
        channel->cal_conf.i.min.adc = current.min_adc;

        channel->cal_conf.i.mid.dac = channel->I_CAL_VAL_MID;
        channel->cal_conf.i.mid.val = current.mid;
        channel->cal_conf.i.mid.adc = current.mid_adc;

        channel->cal_conf.i.max.dac = channel->I_CAL_VAL_MAX;
        channel->cal_conf.i.max.val = current.max;
        channel->cal_conf.i.max.adc = current.max_adc;

        current.level = LEVEL_NONE;
    }

    resetChannelToZero();

    return persist_conf::saveChannelCalibration(channel);
}
示例#7
0
int16_t
parse_cmd_irmp_receive (char *cmd, char *output, uint16_t len)
{
  irmp_data_t irmp_data;
  return (irmp_read (&irmp_data)
	  ? ECMD_FINAL (sprintf_P (output, PSTR ("%d:%04X:%04X:%02X\n"),
				   irmp_data.protocol,
				   irmp_data.address,
				   irmp_data.command,
				   irmp_data.flags)) : ECMD_FINAL_OK);
}
示例#8
0
/**
 * \ingroup tcpcmdcommon
 * \b MAC-Befehl zeige eigene MAC-Adresse
 */
int16_t command_mac (char *outbuffer)
{
	if (outbuffer) {
		sprintf_P(outbuffer,PSTR("250 ok. My MAC: %2x:%2x:%2x:%2x:%2x:%2x\r\n"),mymac[0],mymac[1],mymac[2],mymac[3],mymac[4],mymac[5]);
		return strlen(outbuffer);
	}
	else {
		usart_write("My MAC: %2x:%2x:%2x:%2x:%2x:%2x\r\n",mymac[0],mymac[1],mymac[2],mymac[3],mymac[4],mymac[5]);
		return 0;
	}
}
示例#9
0
void widget_acc_total_draw(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t flags)
{
	uint8_t lh = widget_label_P(PSTR("TotAcc"), x, y);

	float val = fc.acc.total_gui_filtered;

	char text[10];
	sprintf_P(text, PSTR("%0.1f"), val);

	widget_value_int(text, x, y + lh, w, h - lh);
}
示例#10
0
static void menu_action_sdfile(const char* filename, char* longFilename)
{
    char cmd[30];
    char* c;
    sprintf_P(cmd, PSTR("M23 %s"), filename);
    for(c = &cmd[4]; *c; c++)
        *c = tolower(*c);
    enquecommand(cmd);
    enquecommand_P(PSTR("M24"));
    lcd_return_to_status();
}
示例#11
0
void DOS::ChannelTalk(byte channel)
{
#ifdef DEBUG
    Serial.print("TALK: ");
    sprintf_P(_DataBuffer, (PGM_P)F("cmd: %s (len: %d) "), _channels[channel].cmd->str,_channels[channel].cmd->strLen);
    Log(Information, FAC_IFACE, _DataBuffer);
#endif
    if (!Command(channel, ATN_CODE_TALK))
        Load(channel);
    return;
}
示例#12
0
static void
unescape_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
			void *instance_context, JSNode *result_return,
			JSNode *args)
{
  unsigned char *dp;
  unsigned int n, i;
  JSNode *source;
  JSNode source_n;

  if (args->u.vinteger != 1)
    {
      sprintf_P (vm->error, b_core_string_3);
      js_vm_error (vm);
    }
  if (args[1].type == JS_STRING)
    source = &args[1];
  else
    {
      js_vm_to_string (vm, &args[1], &source_n);
      source = &source_n;
    }

  /*
   * Allocate the result string, Let's guess that we need at least
   * <source->u.vstring->len> bytes of data.
   */
  n = source->u.vstring->len;
  dp = source->u.vstring->data;
  js_vm_make_string (vm, result_return, NULL, n);
  result_return->u.vstring->len = 0;

  /*
   * Scan for escapes requiring characters.
   */
  for (i = 0; i < n;)
    {
      unsigned int c = dp[i];

      if (c != '%')
	i += 1;
      else if (i <= n - 6 && dp[i + 1] == 'u'
	       && scanhexdigits (dp + i + 2, 4, &c))
	i += 6;
      else if (i <= n - 3 && scanhexdigits (dp + i + 1, 2, &c))
	i += 3;
      else
	{
	  c = dp[i];
	  i += 1;
	}
      EMIT_TO_RESULT (c);
    }
}
示例#13
0
void DisplayPumpStatus(){
     char SPump[20],lcdteks[20];

	 if (IsNewPumpStatus==True){
	     IsNewPumpStatus=False;
		 BackLightTrig();
		 StrPosCopy(strPumpStatus,SPump,0,PumpCountMax);
		 sprintf_P(lcdteks,PSTR("%s"),SPump);
         lcd_print(4,1,lcdteks);
     	 }
}
示例#14
0
char * iptostr( long IP, char * strIP )
{
	// Union für IP
	union IP_ADDRESS IPnum;

	IPnum.IP = IP;
	
	sprintf_P( strIP, PSTR("%d.%d.%d.%d"), IPnum.IPbyte[0],IPnum.IPbyte[1],IPnum.IPbyte[2],IPnum.IPbyte[3]);
	
	return( strIP );
}
示例#15
0
文件: acc.cpp 项目: ChrisDD11/SkyDrop
void widget_accx_draw(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t flags)
{
	uint8_t lh = widget_label_P(PSTR("Acc X"), x, y);

	float val = fc.acc_data.x / 100.0;

	char text[10];
	sprintf_P(text, PSTR("%0.1f"), val);

	widget_value_int(text, x, y + lh, w, h - lh);
}
static void lcd_menu_change_material_remove_wait_user_ready()
{
    current_position[E_AXIS] = 0;
    plan_set_e_position(current_position[E_AXIS]);
    lcd_change_to_menu(lcd_menu_change_material_insert_wait_user, MAIN_MENU_ITEM_POS(0));
    
    char buffer[32];
    enquecommand_P(PSTR("G28 X0 Y0"));
    sprintf_P(buffer, PSTR("G1 F%i X%i Y%i"), int(homing_feedrate[0]), X_MAX_LENGTH/2, 10);
    enquecommand(buffer);
}
示例#17
0
static void laser_set_focus(float f_length) {
	if (!has_axis_homed[Z_AXIS]) {
		enquecommand_P(PSTR("G28 Z F150"));
	}
	focalLength = f_length;
	float focus = LASER_FOCAL_HEIGHT - f_length;
	char cmd[20];

	sprintf_P(cmd, PSTR("G0 Z%s F150"), ftostr52(focus));
	enquecommand(cmd);
}
示例#18
0
文件: crc_ecmd.c 项目: asuro/ethersex
int16_t
parse_cmd_crc_calc(char *cmd, char *output, uint16_t len)
{
  uint8_t *p;
  uint16_t crc = 0xffff;

  for (p = 0; p < (uint8_t *) CRC_BYTE_POS; p++)
    crc = _crc16_update(crc, pgm_read_byte(p));

  return ECMD_FINAL(sprintf_P(output, PSTR("%.4X"), crc));
}
示例#19
0
文件: kml.cpp 项目: ChrisDD11/SkyDrop
void kml_step()
{
	if (fc.gps_data.valid)
	{
		char line[79];
		char tmp1[16];
		char tmp2[16];

		sprintf_P(tmp1, PSTR(" %+010ld"), fc.gps_data.longtitude);
		memcpy((void *)tmp1, (void *)(tmp1 + 1), 3);
		tmp1[3] = '.';

		sprintf_P(tmp2, PSTR(" %+011ld"), fc.gps_data.latitude);
		memcpy((void *)tmp2, (void *)(tmp2 + 1), 4);
		tmp2[4] = '.';

		sprintf_P(line, PSTR("%s,%s,%0.0f"), tmp1, tmp2, fc.altitude1);
		kml_writeline(line);
	}
}
示例#20
0
文件: ui.c 项目: idaohang/thattaway
//draws a single line with destination info
//  const uint8_t row - the row to draw the line on
//  const loc_state_t* loc - GPS location information
void ui_draw_dest_info( const uint8_t row, const loc_state_t* loc ){
  char small_buffer[SMALL_BUF_LEN];

  lcd_clearline(row);
  lcd_gotoxy(0, row);

  //only print info if we have enough satellites
  if( (loc->sats) >= MIN_SATS ){
    //print the distance
    if( (loc->distance) >= 1000000ul ){ //megameters
      sprintf_P( small_buffer,
                 PSTR("%lu.%dMm"),
                 (unsigned long)(loc->distance)/1000000ul,
                 (int16_t)((loc->distance)/10000ul)%100 );
      lcd_puts( small_buffer );
    } else if( (loc->distance) >= 1000 ){ //kilometers
      sprintf_P( small_buffer,
                 PSTR("%lu.%dkm"),
                 (unsigned long)(loc->distance)/1000,
                 (int16_t)((loc->distance)/10)%100 );
      lcd_puts( small_buffer );
    } else { //meters
      sprintf_P( small_buffer,
                 PSTR("%lum"),
                 (unsigned long)(loc->distance) );
      lcd_puts( small_buffer );
    }

    lcd_gotoxy(8, row);
    //direction of travel
    ui_print_cardinal( loc->heading );

    //print the heading (the \xDF is for something that looks like a degree
    // symbol)
    lcd_gotoxy(11, row);
    sprintf_P( small_buffer, PSTR("%d\xDF"), loc->deltaHeading );
    lcd_puts( small_buffer );
  } else {
    lcd_puts_P("Too few sats");
  }
}
/* ======================================================================
Function: decode_volt
Purpose : print the voltage value
Input   : voltage (mV)
          index of sensor number (0 to 3)
====================================================================== */
char * decode_volt(uint16_t volt, char * index)
{
  // convert voltage to V format xx.yyy
  sprintf_P(pbuf, PSTR("\"volt%s\":%s"), index);
  #ifdef ARDUINO
    dtostrf(volt/1000.0f, 5, 3, pbuf+strlen(pbuf));
  #else
    ftoa(volt/1000.0f, pbuf+strlen(pbuf), 3 );
  #endif

  return pbuf;
}
示例#22
0
void gui_set_gps_detail_loop()
{
	disp.LoadFont(F_TEXT_S);
	uint8_t f_h = disp.GetAHeight() + 1;

	disp.GotoXY(0, 0);
	fprintf_P(lcd_out, PSTR("Lat: %s"), fc.gps_data.cache_gui_latitude);
	disp.GotoXY(0, f_h);
	fprintf_P(lcd_out, PSTR("Lon: %s"), fc.gps_data.cache_gui_longtitude);
	disp.GotoXY(0, f_h * 2);
	fprintf_P(lcd_out, PSTR("HDOP: %5.2f     VDOP: %5.2f"), fc.gps_data.hdop, fc.gps_data.vdop);
	disp.GotoXY(0, f_h * 3);
	fprintf_P(lcd_out, PSTR("geoid: %5.2f    Alt: %6.1f"), fc.gps_data.geoid, fc.gps_data.altitude);

	char tmp[10];

	sprintf_P(tmp, PSTR("%d/%d"), fc.gps_data.sat_used, fc.gps_data.sat_total);
	gui_raligh_text(tmp, GUI_DISP_WIDTH, 0);
	switch (fc.gps_data.fix)
	{
		case(1):
				strcpy_P(tmp, PSTR("No Fix"));
		break;
		case(2):
				strcpy_P(tmp, PSTR("2D Fix"));
		break;
		case(3):
				strcpy_P(tmp, PSTR("3D Fix"));
		break;
	}
	gui_raligh_text(tmp, GUI_DISP_WIDTH, f_h);

	disp.LoadFont(F_TEXT_S);
	for (uint8_t i=0; i < GPS_SAT_CNT; i++)
	{
//		uint8_t x = i < 6 ? (GUI_DISP_WIDTH  * 1 / 4) : (GUI_DISP_WIDTH  * 3 / 4);
//		uint8_t y = (3.5 + i % 6) * f_h;
//
//		x -= GUI_DISP_WIDTH / 8;
//
//		disp.GotoXY(x, y);
//		if (fc.gps_data.sat_id[i] != 0)
//			fprintf_P(lcd_out, PSTR("%03d: %d"), fc.gps_data.sat_id[i], fc.gps_data.sat_snr[i]);

		if (fc.gps_data.sat_id[i] == 0)
			continue;

		uint8_t x = 7 * i;
		uint8_t y = GUI_DISP_HEIGHT - 2 - fc.gps_data.sat_id[i] / 3;
		disp.DrawRectangle(x, y, x + 5, GUI_DISP_HEIGHT - 1, 1, 1);
	}

}
示例#23
0
/**
 * \brief       Send a heartbeat message
  */
void xPL::SendHBeat()
{
  last_heartbeat = millis();
  char buffer[XPL_MESSAGE_BUFFER_MAX];

//  sprintf_P(buffer, PSTR("xpl-stat\n{\nhop=1\nsource=%s-%s.%s\ntarget=*\n}\n%s.%s\n{\ninterval=%d\n}\n"), source.vendor_id, source.device_id, source.instance_id, XPL_HBEAT_ANSWER_CLASS_ID, XPL_HBEAT_ANSWER_TYPE_ID, hbeat_interval);

  sprintf_P(buffer, PSTR("xpl-stat\n{\nhop=1\nsource=%s-%s.%s\ntarget=*\n}\n%s.%s\n{\ninterval=%d\nport=%d\nremote-ip=%d.%d.%d.%d\nversion=1.0\n}\n"), source.vendor_id, source.device_id, source.instance_id, XPL_HBEAT_ANSWER_CLASS_ID, XPL_HBEAT_ANSWER_TYPE_ID, hbeat_interval, udp_port, ip[0], ip[1], ip[2], ip[3]);

  //(*SendExternal)(buffer);
  SendMessage(buffer);
}
/* ======================================================================
Function: decode_temp
Purpose : print the temperature value
Input   : temp (*100)
          index of sensor number (0 to 3)
====================================================================== */
char * decode_temp(int16_t temp, char * index)
{
  // convert temperature to format xx.yy
  sprintf_P(pbuf, PSTR("\"temp%s\":"), index);
  #ifdef ARDUINO
    dtostrf(temp/100.0f, 4, 2,  pbuf+strlen(pbuf));
  #else
    ftoa(temp/100.0f, pbuf+strlen(pbuf), 2 );
  #endif

  return pbuf;
}
示例#25
0
/**
 * \brief       Send a heartbeat message
  */
void xPL::SendHBeat(bool firstRun)
{
  last_heartbeat = millis();
  char buffer[XPL_MESSAGE_BUFFER_MAX];

  sprintf_P(buffer, PSTR("xpl-stat\n{\nhop=1\nsource=%s-%s.%s\ntarget=*\n}\n%s.%s\n{\ninterval=%d\n%s}\n"), source.vendor_id, source.device_id, source.instance_id, XPL_HBEAT_ANSWER_CLASS_ID, XPL_HBEAT_ANSWER_TYPE_ID, hbeat_interval, firstRun ? "init=true\n" : "");

//  sprintf_P(buffer, PSTR("xpl-stat\n{\nhop=1\nsource=%s-%s.%s\ntarget=*\n}\n%s.%s\n{\ninterval=%d\nport=3865\nremote-ip=192.168.4.133\nversion=1.0\n%s}\n"), source.vendor_id, source.device_id, source.instance_id, XPL_HBEAT_ANSWER_CLASS_ID, XPL_HBEAT_ANSWER_TYPE_ID, hbeat_interval, firstRun ? "init=true\n" : "");

  //(*SendExternal)(buffer);
  SendMessage(buffer);
}
示例#26
0
/**
 * \ingroup tcpcmdcommon
 * \b Kamerabild auf SD-Karte speichern
 *
 *	\b Syntax: bild<br>
 *
 *	\author Fred Fröhlich
 */
int16_t Bild_speichern(char *outbuffer)
{
	#if USE_MMC		// nur sinnvoll mit SD-Karte
	unsigned long apos;
	uint16_t a;
	char fname[13];

	max_bytes = cam_picture_store(CAM_RESOLUTION);      //Kamera läd neues Bild in Speicher

	// positive Antwort mit Dateiname in outbuffer speichern
	sprintf_P(fname,PSTR("%02i%02i%02i%02i.jpg"),TM_DD,TM_hh,TM_mm,TM_ss);
	File *picfile = f16_open(fname,"a");
	if (picfile) {
		apos = 0;
		do {
			a = 0;
			do {
				cam_data_get(apos);
				apos++;
				a++;
				if(a==512) break;
			} while(apos < max_bytes);
			fat16_write_file(picfile, (uint8_t *)&cam_dat_buffer[0], a);

		} while(apos < max_bytes);

		f16_close(picfile);

		if (outbuffer) {
			sprintf_P(outbuffer,PSTR("250 Datei: %s"),fname);
			return strlen(outbuffer);	// OK: 250 und Dateiname
		}
		else
			return 0;
	}
	else
	#endif
		return cmd_550(outbuffer);	// Fehler zurückgeben
}
示例#27
0
void gui_set_time_item(uint8_t index, char * text, uint8_t * flags, char * sub_text)
{
	uint8_t sec;
	uint8_t min;
	uint8_t hour;
	uint8_t day;
	uint8_t wday;
	uint8_t month;
	uint16_t year;

	datetime_from_epoch(time_get_actual(), &sec, &min, &hour, &day, &wday, &month, &year);

	switch (index)
	{
		case (0):
			sprintf_P(text, PSTR("Time"));
			sprintf_P(sub_text, PSTR("%02d:%02d.%02d"), hour, min, sec);
			*flags |= GUI_LIST_SUB_TEXT;
		break;

		case (1):
			sprintf_P(text, PSTR("Date"));
			sprintf_P(sub_text, PSTR("%02d/%02d/%04d"), day, month, year);
			*flags |= GUI_LIST_SUB_TEXT;
		break;

		case (2):
			sprintf_P(text, PSTR("Time Zone"));
			sprintf_P(sub_text, PSTR("UTC %+0.1f"), config.system.time_zone / 2.0);
			*flags |= GUI_LIST_SUB_TEXT;
		break;

		case (3):
			sprintf_P(text, PSTR("DST"));
			if (config.system.time_flags & TIME_DST)
				*flags |= GUI_LIST_CHECK_ON;
			else
				*flags |= GUI_LIST_CHECK_OFF;
		break;

		case (4):
			sprintf_P(text, PSTR("Sync with GPS"));
			if (config.system.time_flags & TIME_SYNC)
				*flags |= GUI_LIST_CHECK_ON;
			else
				*flags |= GUI_LIST_CHECK_OFF;
		break;
	}
}
示例#28
0
void ui_control_menu(){
	
	char key = 0;
	
	sprintf_P(lcd_buf_l1, PSTR("Control menu:"));
	sprintf_P(lcd_buf_l2, PSTR("1=Addr, 2=Clock, 0=Cancel"));
	lcd_write_buffer(lcd_buf_l1, lcd_buf_l2);
	
    key = keypad_get_input();
	
	if(key == '1'){
        //Support only IP changing for now
        change_addr_ip();
        //change_addr();
        return;
	}
    
    if(key == '2'){
        change_time();
        return;
    }
}
示例#29
0
void change_addr_ip(){
    
    char key = 0;
    
    sprintf_P(lcd_buf_l1, PSTR("New IP"));
    sprintf_P(lcd_buf_l2, PSTR("%03d.%03d.%03d.%03d"), _network_ip_addr[0], _network_ip_addr[1], _network_ip_addr[2], _network_ip_addr[3]);
    lcd_write_buffer(lcd_buf_l1, lcd_buf_l2);
    
    unsigned int idx = 0;
    do{
        key = keypad_get_input();   //Note that this is blockin function
        
        if((key >= '0') && (key <= '9')){
            
            lcd_buf_l2[idx++] = key;
            
            if(idx == 15){	//Stay on last character
                idx--;
            }
            
            if(idx == 3 || idx == 7 || idx == 11){	//Jump over periods
                idx++;
            }
            
        }
        
        //Disp can be refreshed directly because keys are read with blocking function
        disp_refresh();
        
        //Cancel without changes
        if(key == 'C'){
            return;
        }
        
    }while(key != 'A');
    
    sscanf_P(lcd_buf_l2, PSTR("%u.%u.%u.%u"), _network_ip_addr, _network_ip_addr+1, _network_ip_addr+2, _network_ip_addr+3);	//Read user given data
    
}
/* ======================================================================
Function: decode_bat
Purpose : print the battery voltage value
Input   : battery (mV)
          index of sensor number (0 to 3)
====================================================================== */
char * decode_bat(uint16_t bat, char * index)
{
  sprintf_P(pbuf, PSTR("\"bat%s\":"), index);

  #ifdef ARDUINO
    dtostrf(bat/1000.0f, 5, 3, pbuf+strlen(pbuf));
  #else
    ftoa(bat/1000.0f, pbuf+strlen(pbuf), 3 );
    //sprintf(pbuf, "\"bat%s\":%.3f", index, bat/1000.0f );
  #endif

  return pbuf;
}