Поточний час: 19 серп 2025, 00:58

Часовий пояс: UTC + 2 години



Почати нову тему Відповісти на тему  [ Повідомлень: 5 ] 
Автор Повідомлення
#139924Повідомлення 17 серп 2025, 23:30 
Не в мережі

Звідки: Україна, Київ
Дякував (ла) 1 Подякували 0
Хочу електротранспорт: Електровелосипед
Доброго времени суток.

Заканчиваю переделку велосипеда и решил создать тему, чтоб поделиться опытом.
Велосипед Flyer с двигателем на Panasonic 26 вольт, 8ми скоростная планетарная втулка Shimano.

Задача: сделать велосипед для езды в горы с грузом.

Что сделано:
1. Заменен контроллер на китайский синусный 15А. Поставлен курок газа.
2. Аккумулятор перепакован на 36В. 10S4P
3. Добавлен микроконтроллер для чтения Torque датчика педалей и организации ассистента.

Немного истории.
Сначала пытался переделать стандартный контроллер. Меня устраивало как он работал в режиме ассистента, но не хватало мощности. При увеличении напряжения батареи контроллер стал лучше тянуть, но перестала включаться фара. После попытки исправить проблему с фарой контроллер ушел в ошибку и не вернулся. Экспериментировал с подключением контроллера stm32 на родную силовую плату вместо штатного контроллера, но не довел до ума и отложил. Приступил к реализации плана Б, как более быстрого - замена на китайский контроллер. Купил, подключил, проверил - все работает, газует. Прокатился с курком газа. Мощность есть. Но не очень удобно газовать пальцем и крутить педали, особенно по неровным дорогам. Захотел добавить помощник педалей.

Дальше я добавлю фото Велосипеда, Двигателя, добавленного микроконтроллера stm32, схемы подключения


Додаткові файли:
20250814_123330.jpg
20250814_123330.jpg [ 311.5 КБ | Переглядів: 98 ]
Коментарій до файлу: Двигатель с замененным контроллером
20250805_144151.jpg
20250805_144151.jpg [ 358.87 КБ | Переглядів: 98 ]
Коментарій до файлу: Подключенная STM32F103C8
20250815_194158.jpg
20250815_194158.jpg [ 512.43 КБ | Переглядів: 98 ]
Коментарій до файлу: Схема подключения stm32
Schema_v1_2.png
Schema_v1_2.png [ 77.17 КБ | Переглядів: 98 ]
Повернутися до початку
 Профіль  
Відповісти цитуючи  
 Заголовок повідомлення: Код для микроконтроллера stm32
#139925Повідомлення 17 серп 2025, 23:43 
Не в мережі

Звідки: Україна, Київ
Дякував (ла) 1 Подякували 0
Хочу електротранспорт: Електровелосипед
Код я писал в Arduino IDE.
Спасибо проекту https://github.com/RoboDurden/openPanasonicBike
Функционал минимальный. Подключена одна кнопка для управления. Кнопка Включает/Выключает ассистент педалей, а так же при удержании кнопки включает малый ход двигателя для помощи при ручном толкании велосипеда.
Помощник пока работает не идеально. Возможно позже доработаю код. Пока выложу тот что есть.
Код:
Код:
//Torque Sensor Panasonic Motor Velo VERSION 1.2
unsigned long iTimeRead = 0;
unsigned long iTimeToStop = 0;
unsigned long iTimeToStop2 = 0;
unsigned long iTimeToRun = 0;
unsigned long iTimePedalIdle = 0;
unsigned long iTimeSpeedDown = 0;
unsigned long iTimePressButton = 0;
unsigned long iReads = 0;
unsigned long iReads2 = 0;
unsigned long iNow = 0;
unsigned long SpeedRead = 0;
unsigned long SpeedReadPrev = 0;
unsigned long iReadButton = 0;
float fReadTorque = 0;
float fTorquePrev = 0;
float fTorque_idle = 0;
float fTorque_idle_min = 0;
float fTorque_idle_max = 0;
float fTorque_dif = 0;
float fTorqueMin = 0; // for value torque when no pedaling
int iSpeed = 0;
int iSentSpeed = 0;
int i = 0;
int iSpeedStep = 0;
bool RunMot = 1;
bool Assist_ON = 0; // ON / OFF pedal assistant
bool Helper_ON = 0; // Run small speed to help push a bike with your hands
const int sizeArray = 2;
float TorqueDifArray[sizeArray] = {};
int ArrCount = 0;

void setup() {
  #define TIME_READ 100  // ms to integrate analogRead
  #define TIME_READY 500 // ms to read lowest torque before being ready to ride
  #define TIME_TO_STOP 2000 // ms to Emergency stop motor
  #define TIME_TO_RUN 600 // ms to start pedal assist
  #define TIME_PEDAL_IDLE 1500 // ms. Time to detect pedaling idle
  #define TIME_SPEED_DOWN 600 // ms. Time to down speed motor to 0
 // #define TORQUE_DIF 30 // Difference betwin fTorqueMin and Max Torque
  #define TORQUE_DIF_NORMAL 25 // Difference Torque to normal pedaling mode
  #define iSPEED_START 85 // start value for iSpeed
  #define iSPEED_END 255 // end value for iSpeed
  //#define POLUSES 24 // how many poluses have motor

  #define pin_torque_Pwm PA8
  #define pin_torque_read PA0
  #define pin_Mot PA3
  #define pin_Speed_read PB10
  #define pin_Button PA6
  #define pin_Buzzer PB0

  pinMode(pin_torque_Pwm, OUTPUT);
  pinMode(pin_torque_read,INPUT);
  pinMode(pin_Mot,OUTPUT);
  pinMode(pin_Speed_read,INPUT);
  pinMode(pin_Button,INPUT);
  pinMode(pin_Buzzer, OUTPUT);

  tone(pin_torque_Pwm,65535);

  iTimeRead = millis() + TIME_READ;
  iTimeToStop = millis() + TIME_TO_STOP;
  iTimeToStop2 = millis() + TIME_TO_STOP;
  iTimeToRun = millis() + TIME_TO_RUN;
  iTimePedalIdle = millis() + TIME_PEDAL_IDLE;
  iTimeSpeedDown = millis() + TIME_SPEED_DOWN;
  iSpeed = iSPEED_START;
}

void loop() {
  iNow = millis();

  SpeedRead = pulseIn(pin_Speed_read, HIGH, 40000L);
  if (SpeedRead > 0)
    SpeedRead = 1000000 / SpeedRead;

  iTimeRead = millis() + TIME_READ;

  for (i = 0; iTimeRead > millis(); i++) {
    iReadButton += analogRead(pin_Button);
    fReadTorque += analogRead(pin_torque_read);
  }
  fReadTorque /= i;
  fReadTorque = 100 / fReadTorque;

  int iButton = iReadButton / i;
  iReadButton = 0;

  if (iButton > 500){ // Button operations
    if (iTimePressButton == 0)
      iTimePressButton = iNow;
    if ((iNow - iTimePressButton) > 1000){
      analogWrite(pin_Mot, 80);
      Helper_ON = 1;
    }
  } else {
    if (iTimePressButton > 0 && iNow - iTimePressButton < 500){
      if (Assist_ON) {
        analogWrite(pin_Buzzer, 150);
        delay(100);
        analogWrite(pin_Buzzer, 0);
        delay(100);
        analogWrite(pin_Buzzer, 150);
        delay(100);
        analogWrite(pin_Buzzer, 0);
        Assist_ON = 0;
      }
      else {
        analogWrite(pin_Buzzer, 150);
        delay(100);
        analogWrite(pin_Buzzer, 0);
        Assist_ON = 1;
      }
    }
    if (iNow - iTimePressButton > 1000) {
      analogWrite(pin_Mot, 0);
      Helper_ON = 0;
    }
    iTimePressButton = 0;
  }
 
  if (fTorqueMin == 0)
    fTorqueMin = fReadTorque;
  // if (fTorqueMin == 0 && TIME_READY < iNow)
  //   fTorqueMin = fReadTorque;
  // if (fReadTorque < fTorqueMin)
  //   fTorqueMin = fReadTorque;

  if (iTimePedalIdle > iNow) { // Detect pedal idle
    fTorque_idle = abs(fReadTorque - fTorquePrev);
    if (fTorque_idle < fTorque_idle_min || fTorque_idle_min == 0)
      fTorque_idle_min = fTorque_idle;
    if (fTorque_idle > fTorque_idle_max || fTorque_idle_max == 0)
      fTorque_idle_max = fTorque_idle;
    if (fTorque_idle_max - fTorque_idle_min > 10 || SpeedRead > 0){
      fTorque_idle_min = 0;
      fTorque_idle_max = 0;
      iTimePedalIdle = millis() + TIME_PEDAL_IDLE;
    }
  }
  else {
    if (fTorque_idle_max - fTorque_idle_min <= 10){
      fTorqueMin = fTorquePrev;
    }
    fTorque_idle_min = 0;
    fTorque_idle_max = 0;
    iTimePedalIdle = millis() + TIME_PEDAL_IDLE;
  }

  iSpeedStep = 12;
  if ((iSpeed-iSPEED_START) <= 20 && SpeedRead < 120) // smooth start from 0 speed
    iSpeedStep = iSpeedStep * (iSpeed - iSPEED_START) / 20 + 1;

  fTorque_dif = fReadTorque-fTorqueMin;
  TorqueDifArray[ArrCount] = fTorque_dif;
  ArrCount++;
  if (ArrCount == sizeArray)
    ArrCount = 0;
  fTorque_dif = 0;
  for(i = 0; i < sizeArray; i++)
    fTorque_dif += TorqueDifArray[i];
  fTorque_dif /= sizeArray;

  if (SpeedRead > 0 && iSpeed > iSPEED_START)
    fTorque_dif += 30; //Torque correction

  if (fTorque_dif > TORQUE_DIF_NORMAL) {
    iSpeedStep = iSpeedStep-round(iSpeedStep/((fTorque_dif - TORQUE_DIF_NORMAL)/8 + 1))+1;
    if (SpeedRead <= SpeedReadPrev) //waiting stabilization motor speed
      iSpeed += iSpeedStep; //increase speed
    if (iSpeed > iSPEED_END)
      iSpeed = iSPEED_END;
    iSentSpeed = iSpeed;
  }
  else {
    iSpeedStep = iSpeedStep-round(iSpeedStep/((TORQUE_DIF_NORMAL - fTorque_dif)/8 + 1))+1;
    if (fTorque_dif < TORQUE_DIF_NORMAL - 5)
      iSpeed -= iSpeedStep; //decriase speed
    iSentSpeed = iSpeed;
    // iSentSpeed = 0;
  }
  if (fTorque_dif <= 10) {
    if (iTimeSpeedDown < iNow)
      iSentSpeed = 0; //motor speed down to 0 after pause if low torque
  }
  else {
    iTimeSpeedDown = millis() + TIME_SPEED_DOWN;
  }
 
  if (iSpeed <= iSPEED_START){
    iSpeed = iSPEED_START;
    iSentSpeed = 0;
  }
 
  RunMot = 1;

  if (SpeedRead == 0 && iSentSpeed > 0){ // emergency stop motor
    if (iNow > iTimeToStop){
      RunMot = 0;
      iTimeToRun = millis() + TIME_TO_RUN;
    }
  }
  else {
    iTimeToStop = millis() + TIME_TO_STOP;
  }

  if (iSentSpeed > 0 && iTimeToRun < iNow)
    iTimeToStop2 = millis() + TIME_TO_STOP;

  if (iSentSpeed == 0 && iTimeToStop2 < iNow)
    iTimeToRun = millis() + TIME_TO_RUN;

  if (iTimeToRun > iNow) { // pause before start motor after idle
    RunMot = 0;
    // iSpeed = iSPEED_START+1;
    iTimeToStop = millis() + TIME_TO_STOP;
  }

  if (RunMot && Assist_ON){
    analogWrite(pin_Mot, iSentSpeed);
  }
  else if (!Helper_ON){
    analogWrite(pin_Mot, 0);
  }

  Serial.print("fTorqueMin= ");Serial.print(fTorqueMin);
  Serial.print("  fReadTorque= ");Serial.print(fReadTorque);
  Serial.print("  fTorque_dif= ");Serial.print(fTorque_dif);
  Serial.print("  iSpeedStep= ");Serial.print(iSpeedStep);
  Serial.print("  iSentSpeed= ");Serial.print(iSentSpeed);
  Serial.print("  SpeedRead= ");Serial.print(SpeedRead);
  Serial.print("  RunMot= ");Serial.println(RunMot);

  SpeedReadPrev = SpeedRead;
  fTorquePrev = fReadTorque;
  fReadTorque = 0;
  iReads = 0;
}


Повернутися до початку
 Профіль  
Відповісти цитуючи  
#139926Повідомлення 18 серп 2025, 11:27 
Власник електровелосипеда
Не в мережі

Звідки: Днепр
Дякував (ла) 1 Подякували 23
Мій електротранспорт: Євровел, перероблено під ручку газа і 36В, двигун Panasonic NUA028
В мене такий самий велосипед, тільки під іншим брендом.
Переробляв теж схоже.
Відмінності:
Контролер самий дешманський китайський
Ассистента нема, бо мені не потрібен
Перепакував на 36В, двигун нормально це переносить.
Додав ватметра і вивів його на руль. Максимальна потужність в такій конфігурації показує біля 800Вт
Заднє колесо з Шимано 8 мені дісталось трохи проблемне, тому продав його і купив Шимано на 3 передачі. Скажу, що якщо їздити на ньому як на скутері/мопеді, то і того забагато. Вистачає дві передачі.


Повернутися до початку
 Профіль  
Відповісти цитуючи  
#139927Повідомлення 18 серп 2025, 11:59 
Не в мережі

Звідки: Україна, Київ
Дякував (ла) 1 Подякували 0
Хочу електротранспорт: Електровелосипед
Я еще поставил термореле на 70 градусов в разрыв питания контроллера. На всякий случай от перегрева мотора. Все-таки он работал на 200 Ватт, а теперь ему даю до 600 Ватт. Ну и нагрузка предполагается довольно высокая.


Додаткові файли:
20250805_141105.jpg
20250805_141105.jpg [ 258.64 КБ | Переглядів: 55 ]
Повернутися до початку
 Профіль  
Відповісти цитуючи  
#139928Повідомлення 18 серп 2025, 12:04 
Не в мережі

Звідки: Україна, Київ
Дякував (ла) 1 Подякували 0
Хочу електротранспорт: Електровелосипед
А это фото рабочего процесса :)


Додаткові файли:
20250815_194144_2.jpg
20250815_194144_2.jpg [ 438.63 КБ | Переглядів: 53 ]
Повернутися до початку
 Профіль  
Відповісти цитуючи  
Показати повідомлення за:  Поле сортування  
Почати нову тему Відповісти на тему  [ Повідомлень: 5 ]             

Часовий пояс: UTC + 2 години


Хто зараз на конференції

Зараз цей форум переглядають: немає зареєстрованих користувачів і гості: 54


Ви не можете створювати нові теми
Ви не можете відповідати на повідомлення
Ви не можете редагувати свої повідомлення
Ви не можете видаляти свої повідомлення
Ви не можете додавати додаткові файли

Найти:
cron
Створено на основі phpBB® Forum Software © phpBB Group