Полезная информация


Контроллер VESC, FLIPSKY

Автор Said, 14 Дек. 2018 в 21:21

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

РД00

Вторая версия кастомного RT Data.

Спойлер
/*
    Copyright 2017 - 2019 Benjamin Vedder    benjamin@vedder.se

    This file is part of VESC Tool.

    VESC Tool is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    VESC Tool is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */

import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2

import Vedder.vesc.vescinterface 1.0
import Vedder.vesc.utility 1.0
import Vedder.vesc.commands 1.0
import Vedder.vesc.configparams 1.0

Item {
    anchors.fill: parent

    id: rtData
    property Commands mCommands: VescIf.commands()
    property ConfigParams mMcConf: VescIf.mcConfig()
    property bool isHorizontal: rtData.width > rtData.height
    property int gaugeSize: Math.min(width / 2 - 10,
                                    (height - valMetrics.height * 10) /
                                    (isHorizontal ? 1 : 3) - (isHorizontal ? 30 : 20))
    Component.onCompleted: {
       
// --------------- EDIT HERE --------------------
// ------- Gauge max/min values -----------------       
       
        // Motor current max
        currentGauge.maximumValue = mMcConf.getParamDouble("l_current_max")
//        currentGauge.maximumValue = 150 // Manual set

        // Battery current max
        currentInGauge.maximumValue = mMcConf.getParamDouble("l_in_current_max")
//        currentInGauge.maximumValue = 100 // Manual set

        // Power max
        powerGauge.maximumValue = 6000
       
        // Voltage min/max
        voltageInGauge.minimumValue = 48
        voltageInGauge.maximumValue = 56

        // RPM max
        rpmGauge.maximumValue = 6000
       
        mCommands.emitEmptyValues()
    }


    ColumnLayout {
        anchors.fill: parent
        anchors.topMargin: 5

        GridLayout {
            Layout.fillWidth: true
            Layout.fillHeight: true
            columns: isHorizontal ? 4 : 2
            Layout.leftMargin: 5
            Layout.rightMargin: 5
            Layout.topMargin: 5
            Layout.bottomMargin: 5

            CustomGauge {
                id: currentGauge    // MOTOR CURRENT
                Layout.fillWidth: true
                Layout.fillHeight: true
                maximumValue: 100  // Max phase current
                minimumValue: 0
                labelStep: maximumValue > 60 ? 20 : 10
                value: 0
                unitText: "A"
                typeText: "Motor\nCurrent"
                Layout.preferredWidth: gaugeSize
                Layout.preferredHeight: gaugeSize
            }

            CustomGauge {
                id: currentInGauge    // BATTERY CURRENT
                Layout.fillWidth: true
                Layout.fillHeight: true
                maximumValue: 60    //Max battery current
                minimumValue: 0
                labelStep: maximumValue > 60 ? 20 : 10
                value: 0
                unitText: "A"
                typeText: "Battery\nCurrent"
                Layout.preferredWidth: gaugeSize
                Layout.preferredHeight: gaugeSize
            }

            CustomGauge {
                id: voltageInGauge    // VOLTAGE
                Layout.fillWidth: true
                Layout.fillHeight: true
                maximumValue: 42    // 10S fully charged
                minimumValue: 32    // 10S discharged.
                labelStep: 1
                value: 0
                unitText: "V"
                typeText: "Voltage"
                Layout.preferredWidth: gaugeSize
                Layout.preferredHeight: gaugeSize
                centerTextVisible: false
         
                Text {
                        id: voltageLabel
                        color: {color = Utility.getAppHexColor("lightText")}
                        text: "VOLTAGE"
                        font.pixelSize: gaugeSize/15.0
                        anchors.verticalCenterOffset: -gaugeSize/6.5
                        verticalAlignment: Text.AlignVCenter
                        anchors.centerIn: parent
                        anchors.margins: 10
                        font.family:  "Roboto"
                    }
             
                Text {
                        id: voltageValue
                        color: {color = Utility.getAppHexColor("lightText")}
                        text: "36.2"
                        font.pixelSize: gaugeSize/6
                        anchors.verticalCenterOffset: 0
                        verticalAlignment: Text.AlignVCenter
                        anchors.centerIn: parent
                        anchors.margins: 10
                        font.family:  "Roboto"
                    }

                Text {
                        id: voltagePercent
                        color: {color = Utility.getAppHexColor("lightText")}
                        text: "98%"
                        font.pixelSize: gaugeSize/8
                        anchors.verticalCenterOffset: gaugeSize/6
                        verticalAlignment: Text.AlignVCenter
                        anchors.centerIn: parent
                        anchors.margins: 10
                        font.family:  "Roboto"
                    }

                    Text {
                        id: voltagePercentBottom
                        color: {color = Utility.getAppHexColor("lightText")}
                        text: "%"
                        font.pixelSize: gaugeSize/8.0
                        anchors.verticalCenterOffset: gaugeSize/1.4
                        verticalAlignment: Text.AlignVCenter
                        anchors.centerIn: parent
                        anchors.margins: 10
                        font.family:  "Roboto"
                    }
             

            }

            CustomGauge {
                id: powerGauge    // POWER
                Layout.fillWidth: true
                Layout.fillHeight: true
                maximumValue: 2000
                minimumValue: 0
//                tickmarkScale: 0.001
//                tickmarkSuffix: "k"
                labelStep: maximumValue > 2000 ? 500 : 200
                value: 0
                unitText: "W"
                typeText: "Power"
                Layout.preferredWidth: gaugeSize
                Layout.preferredHeight: gaugeSize
            }

            CustomGauge {
                id: rpmGauge
                Layout.fillWidth: true
                Layout.fillHeight: true
                maximumValue: 4000    // 4000 RPM
                minimumValue: 0
                labelStep: 500
                value: -10
                unitText: ""
                typeText: "RPM"
                Layout.preferredWidth: gaugeSize
                Layout.preferredHeight: gaugeSize
            }

            CustomGauge {
                id: dutyGauge
                Layout.fillWidth: true
                Layout.fillHeight: true
                maximumValue: 100
                minimumValue: 0
                labelStep: 10
                value: 0
                unitText: "%"
                typeText: "Duty"
                Layout.preferredWidth: gaugeSize
                Layout.preferredHeight: gaugeSize
            }
        }

        Rectangle {
            id: textRect
            color: Utility.getAppHexColor("darkBackground")

            Rectangle {
                anchors.bottom: valText.top
                width: parent.width
                height: 2
                color: Utility.getAppHexColor("lightAccent")
            }

            Layout.fillWidth: true
            Layout.preferredHeight: valMetrics.height * 5 + 20
            Layout.alignment: Qt.AlignBottom

            Text {
                id: valText
                color: {color = Utility.getAppHexColor("lightText")}
                text: VescIf.getConnectedPortName()
                font.family: "DejaVu Sans Mono"
                verticalAlignment: Text.AlignVCenter
                anchors.fill: parent
                anchors.leftMargin: 10
                anchors.topMargin: 5
            }

            TextMetrics {
                id: valMetrics
                font: valText.font
                text: valText.text
            }
        }
    }

    Timer {
        id: rtTimer
        interval: 100
        running: true
        repeat: true

        onTriggered: {
            if (VescIf.isPortConnected()) {
                        mCommands.getValuesSetup() // For battery % only
                    }
                   
                }
            }


    Connections {
        target: mCommands

        function onValuesSetupReceived(values, mask) {
            currentGauge.value = values.current_motor  // Motor current
            currentInGauge.value = values.current_in    // Battery current
            voltageInGauge.value = values.v_in          // Voltage
            voltageValue.text = parseFloat(values.v_in).toFixed(1)
            voltagePercent.text = parseFloat(values.battery_level * 100.0).toFixed(0) + "%"
            dutyGauge.value = values.duty_now * 100.0  // Duty

            // 10 for inrunners, 14 for outrunners
            var motor_poles = mMcConf.getParamInt("si_motor_poles") / 2   
            rpmGauge.value = values.rpm / motor_poles  // RPM 

            powerGauge.value = (values.current_in * values.v_in)  // Power   

            valText.text =
//                    "Temp MOS  : " + parseFloat(values.temp_mos).toFixed(2) + " \u00B0C\n" +
                    "Temp MOS  : " + parseFloat(values.temp_mos).toFixed(2) + " \u00B0C" +
                    "        Motor kV : " + parseFloat(rpmGauge.value / (values.v_in * values.duty_now)).toFixed(0) + " \n" +
                    "Temp Motor : " + parseFloat(values.temp_motor).toFixed(2) + " \u00B0C\n" +
                    "Ah Draw    : " + parseFloat(values.amp_hours * 1000.0).toFixed(1) + " mAh\n" +
                    "Wh Draw    : " + parseFloat(values.watt_hours).toFixed(2) + " Wh\n" +
                    "Fault      : " + values.fault_str
//                    "Debug      : " + parseFloat(values.battery_level).toFixed(2)
        }
    }
}


Igor1984

Всем привет. Ребята, подскажите пожалуйста, есть способ подбора параметров вручную? Автодетект никак не проходит нормально. Sensorless вперёд нормально крутит, назад медленнее, hfi дёргается, подключаю энкодер калибрую - дёргается...  Нужен pid position control 180. Подвесы для гоупрошек настраивал, а тут никак не получается. Мотор от электроусилителя руля 4 поля, контроллер flipsky mini 6.7 энкодер 5047

alphajeta

можно ли соединить кан шиной юбокс 85150 и флип 75100? пугают что могут не спариться

РД00

Если оба под vesc одной версии, то почему нет. Протокол один.

Igor1984

Подскажите пожалуйста, может быть кто-то сталкивался, как заставить энкодер 5047 работать в режиме датчиков холла (U-V-W)? Вообще датчики холла на вход vesc контроллера отправляют 3,3 или 5в? У кого как определяется положение? У меня во время автодетекта сначала напрягается, потом крутит, потом шагами оборот делает, но по завершении, когда появляются кнопки fwd/rew, при наличии на них, делает четверть оборота.

Mike 372

У датчиков Холла обычно открытый коллектор. Они ничего не отправляют, а замыкают вход на общий.

Igor1984

Спасибо, просто видел на просторах статью где этот энкодер подключали по uvw без замены резюков. попробовал но vsec холла не увидел. Пытаюсь понять что не так делаю.

Igor1984

Попробую подключить как ABI сенсор. Может получится  :bn:

RommT

Цитата: Igor1984 от 20 Янв. 2026 в 22:20Ребята, подскажите пожалуйста, есть способ подбора параметров вручную?

Да, в идеале так и надо делать. У многих китайских Весков параметры определяются неправильно, потому что неоткалиброваны АЦП и делители с левыми резисторами. Калибровать можно подключая вместо мотора сборку из трёх дросселей с точно известными параметрами, или мотор с точно замеренными R и L, а потом корректировать коэффициенты АЦП в прошивке. Но неудобно что каждый раз прошивку придётся перекомпилировать. А чаще бывает что алгоритм автоопределения не способен определить параметры мотора из-за конструкции этого мотора, тогда тоже замерить сторонними приборами и ввести вручную.
Говей МСМ5 14" - железный сейф на колёсике
электро-Ока
Самовар с подвесным МК - 6кВт на киловаттнике

РД00

Цитата: Igor1984 от 21 Янв. 2026 в 10:00Вообще датчики холла на вход vesc контроллера отправляют 3,3 или 5в?
Вход холлов в vesc. 5В туда не надо, это идет на процессор напрямую.

Igor1984

Ребята, спасибо за ответы. Сегодня мучал контроллер туда - сюда. Результат такой: выбор разного количества полей дают разные результаты насыщения магнитного поля. Один раз получилось получить более менее вменяемую реакцию... Но в процессе  настройки pid завис PPM в проге реакция есть, но на контролер сигнал не приходит (зелёный светодиод ярко не светит), естественно сохранил данные по мотору, прошился заново,в итоге вернулся к тому, с чего начал. С подгруженными данными дёргается как Паркинсон... Завтра буду перебирать разные количества полей. Если у кого-то есть методика упрощаещуя этот дочь, подскажите как этот контроллер победить  O_O

Igor1984

Я не могу понять, как выбирать данные и вносить изменения в автодетект, Я пробовал разные варианты при автодетекте, поля, хх, аутранрер, инраннер, (у меня инраннер), прошивка 6.06 детект корявый... Как победить его?

Igor1984

Вот ещё, такая хрень, энкодер стоит напротив вала, на котором круглый магнит... Детект энкодера не происходит, значение 140-210, но если я ставлю магнит не круглый, а плоский от центра вала как радиус то детект энкодера проходит нормально... Фото сделаю завтра, т.к. скорее всего не очень понятно что я имею ввиду

Igor1984

Всем привет. Сегодня разобрался и настроил мотор от электроусилителя руля Рено, PID position 180, На вал установил энкодер AS5047, проблема заключалась в том, что я использовал не подходящий магнит для энкодера!!! Всем спасибо!!!

РД00

А в чем была цель проекта, очень большая сервомашинка ?

Igor1984

Проект ещё в работе. Так сказать в рамках кружка "очумелые ручки" заказал лодку с жёстким корпусом, собираю радиоуправление для лодочного мотора. Цель - потратить в разы меньше денег, чем стоимость классического рулевого управления  :-D

Igor1984

Кстати по поводу не подходящего магнита, график энкодера при калибровке показывает значения от 0 до 360°, причем калибровка завершается без ошибок, в вот сам график выглядит "ступеньками" в общем даже если магнит неодим, не факт что с ним энкодер будет нормально работать.

РД00

Цитата: Igor1984 от 23 Янв. 2026 в 10:06Цель - потратить в разы меньше денег
Ну, пусть расцветают сто цветов. Линейный актуатор на 12В и 50 кг стоит 2к.