static void test_conv_init()
{
    printf("test_conv_init...");

    unsigned int img_width = 512;
    unsigned int img_height = 512;
    unsigned int bitsperpixel = 24;
    int no_of_layers = 3;
    int max_features = 20;
    int reduction_factor = 4;
    int pooling_factor = 2;
    float error_threshold[] = {0.0, 0.0, 0.0};
    unsigned int random_seed = 648326;
    deeplearn_conv conv;

    assert(conv_init(no_of_layers,
                     img_width, img_height,
                     bitsperpixel/8, max_features,
                     reduction_factor, pooling_factor,
                     &conv, error_threshold,
                     &random_seed) == 0);
    conv_free(&conv);

    printf("Ok\n");
}
Exemple #2
0
SetCharset()
{
  CSET charset;
  int rc;
  move(3,0);
  clrtobot();
  if (getdata(3,0, "Enter new charset: ", charset,
      sizeof charset, DOECHO, 1) == -1) return FULLUPDATE;
  if(charset[0] == '\0')
    return PARTUPDATE;
  if(conv_init(charset) == -1) {
    prints("Invalid character set.\n");
#ifndef REMOTE_CLIENT
    return PARTUPDATE;
#endif
  }
  else {
    initscr();
    clear();
  }
  rc = bbs_set_charset(charset);
  if (rc == S_OK)
    prints("New character set was saved.\n");
  else
    prints("New character set NOT saved.\n");
  pressreturn();
  return FULLUPDATE;
}
Exemple #3
0
/**
 * @brief Loads a convolution object from file
 * @param fp File pointer
 * @param conv Convolution object
 * @return zero value on success
 */
int conv_load(FILE * fp, deeplearn_conv * conv)
{
    float * error_threshold;

    if (fread(&conv->reduction_factor, sizeof(int), 1, fp) == 0) {
        return -1;
    }
    if (fread(&conv->pooling_factor, sizeof(int), 1, fp) == 0) {
        return -2;
    }
    if (fread(&conv->random_seed, sizeof(unsigned int), 1, fp) == 0) {
        return -3;
    }
    if (fread(&conv->inputs_across, sizeof(int), 1, fp) == 0) {
        return -4;
    }
    if (fread(&conv->inputs_down, sizeof(int), 1, fp) == 0) {
        return -5;
    }
    if (fread(&conv->inputs_depth, sizeof(int), 1, fp) == 0) {
        return -6;
    }
    if (fread(&conv->max_features, sizeof(int), 1, fp) == 0) {
        return -7;
    }
    if (fread(&conv->no_of_layers, sizeof(int), 1, fp) == 0) {
        return -8;
    }
    if (fread(&conv->enable_learning,
              sizeof(unsigned char), 1, fp) == 0) {
        return -9;
    }
    if (fread(&conv->current_layer, sizeof(int), 1, fp) == 0) {
        return -11;
    }
    if (fread(&conv->training_complete,
              sizeof(unsigned char), 1, fp) == 0) {
        return -12;
    }
    if (fread(&conv->itterations, sizeof(unsigned int), 1, fp) == 0) {
        return -13;
    }

    error_threshold = (float*)malloc(sizeof(float)*conv->no_of_layers);
    if (!error_threshold) {
        return -14;
    }
    if (fread(error_threshold,
              sizeof(float), conv->no_of_layers, fp) == 0) {
        return -15;
    }

    if (conv_init(conv->no_of_layers,
                  conv->inputs_across, conv->inputs_down,
                  conv->inputs_depth, conv->max_features,
                  conv->reduction_factor, conv->pooling_factor,
                  conv, error_threshold,
                  &conv->random_seed) != 0) {
        free(error_threshold);
        return -16;
    }
    free(error_threshold);

    for (int i = 0; i < conv->no_of_layers; i++) {
        if (autocoder_load(fp, conv->layer[i].autocoder, 0) != 0) {
            return -17;
        }
        if (fread(&conv->layer[i].units_across,
                  sizeof(int), 1, fp) == 0) {
            return -18;
        }
        if (fread(&conv->layer[i].units_down,
                  sizeof(int), 1, fp) == 0) {
            return -19;
        }
        if (fread(&conv->layer[i].pooling_factor,
                  sizeof(int), 1, fp) == 0) {
            return -20;
        }
    }

    return 0;
}
Exemple #4
0
int main(int argc, char **argv) {
  char*   infile;
  char*   outfile;
  char*   dot;
  int     ch;
  int     fmt = VTF3_FILEFORMAT_STD_ASCII;
  int     eflag = 0;
  struct stat statbuf;
  elg_ui4 numrec = 0;
  elg_ui4 limrec = 0xFFFFFFFF;
  elg_ui4 limsiz = 0xFFFFFFFF;
  ElgRCB* handle = NULL;
  MYDATA  md = { 0, 0, 0, 0 };

  while ((ch = getopt(argc, argv, "abfghin:r:s:GO")) != EOF) {
    switch (ch) {
    case 'a': fmt = VTF3_FILEFORMAT_STD_ASCII;
              break;
    case 'b': fmt = VTF3_FILEFORMAT_STD_BINARY;
              break;
    case 'f': fmt = VTF3_FILEFORMAT_FST_ASCII;
              break;
    case 'g': genompglop = 0;
              break;
    case 'G': genmpiglop = 0;
              genompglop = 0;
              break;
    case 'i': addidle = 0;
              break;
    case 'n': limrec = atol(optarg);
              break;
    case 'O':
#ifdef VTF3_HAS_OPENMP
	      writeOMP = 1;
              genompglop = 0;
#endif
	      break;
    case 's': limsiz = atol(optarg);
              break;
    case 'r': rmatag = atol(optarg);
              break;
    case 'h':
    case '?': eflag = 1;
              break;
    }
  }

  if ((argc-optind) == 2) {
    infile  = epk_get_elgfilename(argv[optind]);
    outfile = argv[optind+1];
  } else  if ((argc-optind) == 1) {
    infile  = epk_get_elgfilename(argv[optind]);
    outfile = strdup(infile);
    dot = strrchr(outfile, '.');
    *(dot + 1) = 'v';
    *(dot + 2) = 'p';
    *(dot + 3) = 't';
  } else {
    eflag = 1;
  }

  if ( eflag ) {
    fprintf(stderr, "Usage:   %s [-a|-b|-f] [-i] [-g|-G] [-O] [-n #] [-s #]"
                    " [-r #]"
                    " (<infile>.elg | <experiment_archive>) [<outfile>]\n",
                    argv[0]);
    fprintf(stderr, "Options: -a force standard ascii output\n");
    fprintf(stderr, "         -b force binary output\n");
    fprintf(stderr, "         -f force fast ascii output\n");
    fprintf(stderr, "         -g do not generate globalops for OMP barriers\n");
    fprintf(stderr, "         -G do not generate globalops (for MPI + OMP)\n");
    fprintf(stderr, "         -i do not add idle state\n");
    fprintf(stderr, "         -O generate VTF3 OpenMP events\n");
    fprintf(stderr, "         -n stop converting after # records\n");
    fprintf(stderr, "         -s stop converting after # bytes written\n");
    fprintf(stderr, "         -r use # as tag for RMA operations\n");
    fprintf(stderr, "If <outfile> is omitted, <infile>.vpt is used for output\n");
    fflush(stderr);
    exit(EXIT_FAILURE);
  }

  handle = elg_read_open(infile);
  if ( ! handle ) exit(EXIT_FAILURE);
  stat(infile, &statbuf);

  conv_init();
  VTF3_InitTables();
  if ( (fcb = VTF3_OpenFileOutput(outfile, fmt, genmpiglop)) == 0 ) {
    fprintf(stderr, "Can't open output file %s\n", outfile);
    fflush(stderr);
    exit(EXIT_FAILURE);
  }

  wbytes += VTF3_WriteDefversion(fcb, VTF3_GetVersionNumber());
  wbytes += VTF3_WriteDefcreator(fcb, "epilog -> vtf3 converter 1.3");

  while ( elg_read_next(handle, (void*) &md) ) {
    numrec++;

    if ( numrec % 1000 == 0 ) {
      printf("done: %3.0f%%\r", ((double) md.done / statbuf.st_size) * 100.0);
      fflush(stdout);
    }

    if ( numrec > limrec ) {
      printf("Limit of %u records reached.\n", limrec);
      break;
    }
    if ( wbytes > limsiz ) {
      printf("Limit of %ld bytes reached.\n", (long)wbytes);
      break;
    }
  }

  {
  int lid;
  if ( state_idle != -1 && addidle ) {
    for(lid=0; lid<totallocs; lid++) {
      if ( loctab[lid].proc->member[0].id != lid ) {
        wbytes += VTF3_WriteUpfrom(fcb, lasttime*1.0e+10, (int) state_idle,
                                   locmap[lid], VTF3_SCLNONE);
      }
    }
  }
  }

  elg_read_close(handle);
  VTF3_Close(fcb);
  return 0;
}
static void test_conv_image()
{
    printf("test_conv_image...");

    unsigned int img_width = 10;
    unsigned int img_height = 10;
    unsigned int bitsperpixel = 0;
    int no_of_layers = 3;
    int max_features = 20;
    int reduction_factor = 6;
    int pooling_factor = 2;
    float error_threshold[] = {0.0, 0.0, 0.0};
    unsigned int random_seed = 648326;
    unsigned char * img, * img2;
    deeplearn_conv conv;
    float BPerror = -1;
    char plot_filename[256];
    char plot_title[256];

    /* load image from file */
    assert(deeplearn_read_png_file((char*)"Lenna.png",
                                   &img_width, &img_height,
                                   &bitsperpixel, &img)==0);

    img2 = (unsigned char*)malloc(128*128*3*sizeof(unsigned char));
    assert(img2);
    deeplearn_downsample(img, img_width, img_height,
                         img2, 128, 128);
    free(img);
    img = img2;
    img_width = 128;
    img_height = 128;

    assert(conv_init(no_of_layers,
                     img_width, img_height,
                     bitsperpixel/8, max_features,
                     reduction_factor, pooling_factor,
                     &conv, error_threshold,
                     &random_seed) == 0);

    int conv0_size =
        conv.layer[0].units_across *
        conv.layer[0].units_down * max_features;

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < conv0_size; j++) {
            conv.layer[0].convolution[j] = -9999;
        }

        assert(conv_img(img, &conv) == 0);

        /* check that some convolution happened */
        for (int j = 0; j < conv0_size; j++) {
            assert(conv.layer[0].convolution[j] != -9999);
        }

        /* error should be >= 0 */
        assert(conv.BPerror >= 0);
        /* error should be reducing */
        if (i > 0) {
            assert(conv.BPerror < BPerror);
        }
        BPerror = conv.BPerror;
    }

    /* move to hte next layer */
    conv.BPerror = -1;
    conv.current_layer++;

    int conv1_size =
        conv.layer[1].units_across *
        conv.layer[1].units_down * max_features;

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < conv1_size; j++) {
            conv.layer[1].convolution[j] = -9999;
        }

        assert(conv_img(img, &conv) == 0);

        /* check that some convolution happened */
        for (int j = 0; j < conv1_size; j++) {
            assert(conv.layer[1].convolution[j] != -9999);
        }

        /* error should be >= 0 */
        if (!(conv.BPerror >= 0)) {
            printf("\nBPerror: %f\n",conv.BPerror);
        }
        assert(conv.BPerror >= 0);
        /* error should be reducing */
        if (i > 0) {
            assert(conv.BPerror < BPerror);
        }
        BPerror = conv.BPerror;
    }

    sprintf(plot_filename,"/tmp/%s","libdeep_conv.png");
    sprintf(plot_title,"%s","Convolution Training Error");

    assert(conv_plot_history(&conv, plot_filename,
                             plot_title,
                             1024, 640) == 0);
    conv_free(&conv);
    free(img);

    printf("Ok\n");
}
static void test_conv_save_load()
{
    printf("test_conv_save_load...");

    unsigned int img_width = 512;
    unsigned int img_height = 512;
    unsigned int bitsperpixel = 24;
    int i, no_of_layers = 3;
    int max_features = 20;
    int reduction_factor = 4;
    int pooling_factor = 2;
    float error_threshold[] = {0.1, 0.2, 0.3};
    float error_threshold2[] = {0.6, 0.7, 0.8};
    unsigned int random_seed = 648326;
    deeplearn_conv conv1;
    deeplearn_conv conv2;
    FILE * fp;
    char filename[256];

    assert(conv_init(no_of_layers,
                     img_width, img_height,
                     bitsperpixel/8, max_features,
                     reduction_factor, pooling_factor,
                     &conv1, error_threshold,
                     &random_seed) == 0);

    sprintf(filename, "/tmp/%s", "libdeep_conv.dat");

    /* save */
    fp = fopen(filename,"w");
    assert(fp);
    assert(conv_save(fp, &conv1) == 0);
    fclose(fp);

    /* set some different values */
    conv2.reduction_factor = 45;
    conv2.pooling_factor = 8;
    conv2.inputs_across = 100;
    conv2.inputs_down = 200;
    conv2.inputs_depth = 16;
    conv2.no_of_layers = 2;
    conv2.max_features = 15;
    memcpy((void*)conv2.error_threshold,
           error_threshold2,
           conv2.no_of_layers*sizeof(float));
    conv2.random_seed = 20313;
    conv2.enable_learning = 0;
    conv2.current_layer = 4577;
    conv2.training_complete = 3;
    conv2.itterations = 642;
    conv2.layer[0].autocoder=NULL;

    /* load */
    fp = fopen(filename,"r");
    assert(fp);
    assert(conv_load(fp, &conv2) == 0);
    fclose(fp);

    /* compare the results */
    assert(conv2.layer[0].autocoder != NULL);
    assert(conv2.layer[0].autocoder->inputs != NULL);
    assert(conv2.layer[0].autocoder->hiddens != NULL);
    assert(conv1.layer[0].autocoder->NoOfInputs ==
           conv2.layer[0].autocoder->NoOfInputs);
    assert(conv1.layer[0].autocoder->NoOfHiddens ==
           conv2.layer[0].autocoder->NoOfHiddens);
    assert(conv1.reduction_factor == conv2.reduction_factor);
    assert(conv1.pooling_factor == conv2.pooling_factor);
    assert(conv1.random_seed != conv2.random_seed);
    assert(conv1.inputs_across == conv2.inputs_across);
    assert(conv1.inputs_down == conv2.inputs_down);
    assert(conv1.inputs_depth == conv2.inputs_depth);
    assert(conv1.max_features == conv2.max_features);
    assert(conv1.no_of_layers == conv2.no_of_layers);
    assert(conv1.enable_learning == conv2.enable_learning);
    assert(conv1.current_layer == conv2.current_layer);
    assert(conv1.training_complete == conv2.training_complete);
    assert(conv1.itterations == conv2.itterations);
    for (i = 0; i < conv1.no_of_layers; i++) {
        for (int j = 0; j < conv1.layer[i].autocoder->NoOfInputs*
                 conv1.layer[i].autocoder->NoOfHiddens; j++) {
            assert(conv1.layer[i].autocoder->weights[j] > -0.3f);
            assert(conv1.layer[i].autocoder->weights[j] < 0.3f);
            assert(conv2.layer[i].autocoder->weights[j] > -0.3f);
            assert(conv2.layer[i].autocoder->weights[j] < 0.3f);
        }
        assert(conv1.error_threshold[i] == conv2.error_threshold[i]);
        if ((conv1.layer[i].autocoder != NULL) &&
            (conv2.layer[i].autocoder != NULL)) {
            assert(autocoder_compare(conv1.layer[i].autocoder,
                                     conv2.layer[i].autocoder) == 0);
        }
        assert(conv1.layer[i].units_across == conv2.layer[i].units_across);
        assert(conv1.layer[i].units_down == conv2.layer[i].units_down);
        assert(conv1.layer[i].pooling_factor == conv2.layer[i].pooling_factor);
    }

    conv_free(&conv1);
    conv_free(&conv2);

    printf("Ok\n");
}
Exemple #7
0
int main(void)
{

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC_Init();
  MX_TIM2_Init();
  MX_TIM21_Init();

  batpins battery3;
  batpins battery4;
  pwm_timers b3_tims;
  pwm_timers b4_tims;
  batprops props_bat3;
  batprops props_bat4;

  /* Battery 3 */
  b3_tims.conv_timer = htim2;
  b3_tims.dchg_timer = htim21;

  battery3.v_adc_chan = ADC_CHANNEL_4;
  battery3.i_adc_chan = ADC_CHANNEL_8;
  battery3.chg_port = chg_onoff_3_GPIO_Port;
  battery3.chg_pin = chg_onoff_3_Pin;
  battery3.dchg_pin = TIM_CHANNEL_1;
  battery3.conv_chg_pin = TIM_CHANNEL_1;
  battery3.conv_dchg_pin = TIM_CHANNEL_2;
  battery3.pwm_tims = b3_tims;

  props_bat3.i_adc_val = 0;
  props_bat3.v_adc_val = 0;
  props_bat3.adc_val_old = adc_read(battery3.i_adc_chan);
  props_bat3.id_adc_stpt = 400 + props_bat3.adc_val_old;
  props_bat3.ic_adc_stpt = props_bat3.adc_val_old - 600;
  props_bat3.conv_bst_stpt = 200; // Need to calibrate this to boost to desired voltage
  props_bat3.pwm_chg_stpt = 0; 	  // Initialized to 0. Program will change as needed.
  props_bat3.pwm_dchg_stpt = 720; // Initialize near where discharge FET turns on
  props_bat3.pi = 0;

  /* Battery 4 */
  b4_tims.conv_timer = htim2;
  b4_tims.dchg_timer = htim21;

  battery4.v_adc_chan = ADC_CHANNEL_11;
  battery4.i_adc_chan = ADC_CHANNEL_10;
  battery4.chg_port = chg_onoff_4_GPIO_Port;
  battery4.chg_pin = chg_onoff_4_Pin;
  battery4.dchg_pin = TIM_CHANNEL_2;
  battery4.conv_chg_pin = B4_CHG_CHAN; // Change in h file (used in multiple locations, dma_offset func)
  battery4.conv_dchg_pin = TIM_CHANNEL_4;
  battery4.pwm_tims = b4_tims;

  props_bat4.i_adc_val = 0;
  props_bat4.v_adc_val = 0;
  props_bat4.adc_val_old = adc_read(battery4.i_adc_chan);
  props_bat4.id_adc_stpt = 500 + props_bat4.adc_val_old;
  props_bat4.ic_adc_stpt = props_bat4.adc_val_old - 200;
  props_bat4.conv_bst_stpt = 200; // Need to calibrate this to boost to desired voltage
  props_bat4.pwm_chg_stpt = 0; 	  // Initialized to 0. Program will change as needed.
  props_bat4.pwm_dchg_stpt = 720; // Initialize near where discharge FET turns on
  props_bat4.pi = 0;

  /* Initialize global variables */
#ifdef BAT1
  TimeCounter3 = 0;
  TimeCounter4 = 0;
  uint32_t restStartms3 = 0;
  uint32_t i3 = 0;
  uint32_t voltage3 = 0;
  uint32_t current3 = 720;
  status bat_stat3 = OK;
  i3_origin = props_bat3.adc_val_old;
#endif

#ifdef BAT2
  uint32_t restStartms4 = 0;
  uint32_t i4 = 0;
  uint32_t voltage4 = 0;
  uint32_t current4 = 720;
  status bat_stat4 = OK;
  i4_origin = props_bat4.adc_val_old;
#endif

  //uint32_t dc_pwm[1] = {800};//, 500, 200, 300, 400, 500, 600, 700, 250, 750};
  //uint32_t test2[2] = {100, 900};
  //uint32_t sine = 0;

  /* Initialize converter and charge / discharge pins   */
  conv_init(battery3);
  conv_init(battery4);

  //HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_3, &dc_pwm, (uint16_t)1);
  //HAL_Delay(10);
  //HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_4, &dc_pwm[8], (uint16_t)2);
  //HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, 200, (uint16_t)SINE_RES_500HZ);
  //HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_4, 800, (uint16_t)SINE_RES_500HZ); //Bat2 conv dchg
  //pwm_sine_Start(battery3.pwm_tims.conv_timer, battery3.conv_dchg_pin, dc_pwm, sine); // Boost (discharge)
  //pwm_sine_Start(battery3.pwm_tims.conv_timer, battery3.conv_chg_pin,  dc_pwm, sine); // Buck (charge)
  //pwm_sine_Start(battery4.pwm_tims.conv_timer, battery4.conv_dchg_pin, test2, sine); // Boost (discharge)
  //pwm_sine_Start(battery4.pwm_tims.conv_timer, battery4.conv_chg_pin, 400, sine); // Buck (charge)
  //pwm_Set(battery3.pwm_tims.dchg_timer, battery3.dchg_pin, 750);
 // pwm_Set(battery4.pwm_tims.dchg_timer, battery4.dchg_pin, 760);
  //pwm_sine_Start(battery3.pwm_tims.conv_timer, battery3.conv_chg_pin, dc_pwm, sine); // Buck (charge)
  //HAL_GPIO_WritePin(battery3.chg_port, battery3.chg_pin, GPIO_PIN_SET); // Charging On
  //HAL_GPIO_WritePin(battery4.chg_port, battery4.chg_pin, GPIO_PIN_SET); // Charging On
  //pwm_sine_Start(battery4.pwm_tims.conv_timer, battery4.conv_chg_pin, dc_pwm, sine); // Buck (charge)
  //HAL_TIM_PWM_Start(battery4.pwm_tims.conv_timer, battery4.conv_dchg_pin);
  //HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); // Bat1 conv dchg

  uint8_t u8_oc3 = 0;
  uint8_t u8_oc4 = 0;

  // Wait for batteries to be connected
  //while(adc_read(battery3.v_adc_chan) < 500 || adc_read(battery4.v_adc_chan) < 500) {}

  /* Infinite loop */
  while (1)
  {

#ifdef BAT1
	  /* First battery */
	  if(TimeCounter3>=5) // 4ms, ie 2 periods of 500Hz sine wave
	  	  {
	  		  switch(bat_stat3) {
	  		  case DISCHARGE:
	  			  bat_stat3 = discharge_main(battery3, &props_bat3, &restStartms3, i3, bat_stat3);
	  			  break;
	  		  case CC:
	  			  bat_stat3 = chg_ctrl(battery3, &props_bat3, i3, i3_origin);
	  			  //HAL_Delay(1);
	  			  break;
	  		  case CV:
	  			  bat_stat3 = cv_main(battery3, &props_bat3, &restStartms3, i3, i3_origin, bat_stat3);
	  			  break;
	  		  case FULL:
	  			  if(HAL_GetTick() - restStartms3 >= REST)
	  			  {
						props_bat3.i_adc_val = 0;
						props_bat3.v_adc_val = 0;
						props_bat3.adc_val_old = adc_read(battery3.i_adc_chan);
						bat_stat3 = DISCHARGE;
	  			  }
	  			  break;
	  		  case LVDC:
	  			if(HAL_GetTick() - restStartms3 >= REST)
	  			  {
					  props_bat3.i_adc_val = 0;
					  props_bat3.v_adc_val = 0;
					  props_bat3.adc_val_old = adc_read(battery3.i_adc_chan);
					  bat_stat3 = CC;
	  			  }
	  			  break;
	  		  case OK:
	  			  props_bat3.i_adc_val = 0; // normally reset in d/chg func, but not used so reset here
	  			  props_bat3.v_adc_val = 0; // normally reset in d/chg func, but not used so reset here
	  			  bat_stat3 = CC;
	  			  break;
	  		  case OVERCURRENT:
	  			  bat_stat3 = OVERCURRENT;
	  			  break;
	  		  default:
	  			  bat_stat3 = OK;
	  			  break;
	  		  }
	  		  TimeCounter3 = 0;
	  		  i3 = 0;
	  	  }

  	  /* Update ADC readings */
  	  current3 = adc_read(battery3.i_adc_chan);
  	  voltage3 = adc_read(battery3.v_adc_chan);
  	  props_bat3.i_adc_val = props_bat3.i_adc_val + current3;
  	  props_bat3.v_adc_val = props_bat3.v_adc_val + voltage3;

  	  /* Over-current protection */
  	  if(current3>3950 || current3<100)
  	  {
  		  u8_oc3++;
  		  if(u8_oc3 > 15)
  		  {
  			conv_init(battery3);
  			bat_stat3 = OVERCURRENT;
  		  }
  	  }
  	  else
  	  {
  		  u8_oc3 = 0;
  	  }
  	  i3++;
#endif

#ifdef BAT2
	  /* Second battery */
	  if(TimeCounter4>=5) // 4ms, ie 2 periods of 500Hz sine wave
		  {
			  switch(bat_stat4) {
			  case DISCHARGE:
				  bat_stat4 = discharge_main(battery4, &props_bat4, &restStartms4, i4, bat_stat4);
				  break;
			  case CC:
				  bat_stat4 = chg_ctrl(battery4, &props_bat4, i4, i4_origin);
				  break;
			  case CV:
				  bat_stat4 = cv_main(battery4, &props_bat4, &restStartms4, i4, i4_origin, bat_stat4);
				  break;
			  case FULL:
				  if(HAL_GetTick() - restStartms4 >= REST)
				  {
						props_bat4.i_adc_val = 0;
						props_bat4.v_adc_val = 0;
						props_bat4.adc_val_old = adc_read(battery4.i_adc_chan);
						bat_stat4 = DISCHARGE;
				  }
				  break;
			  case LVDC:
				if(HAL_GetTick() - restStartms4 >= REST)
				  {
					  props_bat4.i_adc_val = 0;
					  props_bat4.v_adc_val = 0;
					  props_bat4.adc_val_old = adc_read(battery4.i_adc_chan);
					  bat_stat4 = CC;
				  }
				  break;
			  case OK:
				  props_bat4.i_adc_val = 0; // normally reset in d/chg func, but not used so reset here
				  props_bat4.v_adc_val = 0; // normally reset in d/chg func, but not used so reset here
				  bat_stat4 = CC;
				  break;
			  case OVERCURRENT:
				  bat_stat4 = OVERCURRENT;
				  break;
			  default:
				  bat_stat4 = OK;
				  break;
			  }
			  TimeCounter4 = 0;
			  i4 = 0;
		  }

	  /* Update ADC readings */
  	  current4 = adc_read(battery4.i_adc_chan);
  	  voltage4 = adc_read(battery4.v_adc_chan);
  	  props_bat4.i_adc_val = props_bat4.i_adc_val + current4;
  	  props_bat4.v_adc_val = props_bat4.v_adc_val + voltage4;

  	  /* Over-current protection */
  	  if(current4>3950 || current4<100)
  	  {
  		  u8_oc4++;
  		  if(u8_oc4 > 15)
  		  {
  			conv_init(battery4);
  			bat_stat4 = OVERCURRENT;
  		  }
  	  }
  	  else
  	  {
  		  u8_oc4 = 0;
  	  }
  	  i4++;

#endif

	  HAL_SYSTICK_IRQHandler();

  }


}