Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
17
tools/EVerest-main/lib/everest/can_dpm1000/CMakeLists.txt
Normal file
17
tools/EVerest-main/lib/everest/can_dpm1000/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
add_library(can_dpm1000)
|
||||
add_library(can_protocols::dpm1000 ALIAS can_dpm1000)
|
||||
ev_register_library_target(can_dpm1000)
|
||||
|
||||
target_include_directories(can_dpm1000
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
)
|
||||
|
||||
target_sources(can_dpm1000
|
||||
PRIVATE
|
||||
src/dpm1000.cpp
|
||||
)
|
||||
|
||||
if(BUILD_DEV_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
@@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright Pionix GmbH and Contributors to EVerest
|
||||
#ifndef CAN_PROTOCOL_DPM1000_HPP
|
||||
#define CAN_PROTOCOL_DPM1000_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <linux/can.h>
|
||||
|
||||
namespace can::protocol::dpm1000 {
|
||||
namespace def {
|
||||
|
||||
enum class ErrorType : uint8_t {
|
||||
NO_ERROR = 0xf0,
|
||||
INVALID_NODE_ADDRESS = 0xf1,
|
||||
INVALID_COMMAND = 0xf2,
|
||||
DATA_VERIFICATION_FAULT = 0xf3,
|
||||
ADDRESS_RECOGNITION = 0xf4,
|
||||
};
|
||||
|
||||
enum class MessageType : uint8_t {
|
||||
SET_DATA_REQUEST = 0x00,
|
||||
REQUEST_DATA_BYTE = 0x01,
|
||||
RESPONSE_REQUEST = 0x41,
|
||||
SET_DATA = 0x03,
|
||||
RESPONSE_CONFIGURATION = 0x43,
|
||||
};
|
||||
|
||||
constexpr auto SET_DATA_REQUEST_INPUT_RELAY_BIT_SHIFT = 2;
|
||||
constexpr auto SET_DATA_REQUEST_POWER_BIT_SHIFT = 7;
|
||||
|
||||
enum class ReadValueType : uint16_t {
|
||||
VOLTAGE = 0x0001,
|
||||
CURRENT_REAL_PART = 0x0002,
|
||||
CURRENT_LIMIT = 0x0003,
|
||||
DCDC_TEMPERATURE = 0x0004,
|
||||
AC_VOLTAGE = 0x0005,
|
||||
VOLTAGE_LIMIT = 0x0006,
|
||||
CURRENT = 0x0007, // how is this different from the real part?
|
||||
PFC0_VOLTAGE = 0x0008,
|
||||
PFC1_VOLTAGE = 0x000A,
|
||||
ENV_TEMPERATURE = 0x000B,
|
||||
AC_VOLTAGE_PHASE_A = 0x000C,
|
||||
AC_VOLTAGE_PHASE_B = 0x000D,
|
||||
AC_VOLTAGE_PHASE_C = 0x000E,
|
||||
PFC_TEMPERATURE = 0x0010,
|
||||
POWER_LIMIT = 0x0014,
|
||||
ALARM = 0x0040,
|
||||
DEFAULT_CURRENT_LIMIT = 0x0019,
|
||||
};
|
||||
|
||||
enum class SetValueType : uint16_t {
|
||||
DEFAULT_CURRENT_LIMIT = 0x0019,
|
||||
POWER_LIMIT = 0x0020,
|
||||
VOLTAGE = 0x0021,
|
||||
CURRENT_LIMIT = 0x0022,
|
||||
SERIES_PARALLEL_MODE = 0x0023,
|
||||
DEFAULT_OUTPUT_VOLTAGE = 0x0024,
|
||||
SWITCH_ON_OFF_SETTING = 0x0030,
|
||||
INPUT_RELAY_POWER_OFF_SETTING = 0x0035,
|
||||
};
|
||||
|
||||
enum class Alarm : uint8_t {
|
||||
FUSE_BURN_OUT = 2,
|
||||
PFC_DCDC_COMMUNICATION_ERROR = 3,
|
||||
UNBALANCED_BUS_VOLTAGE = 6,
|
||||
BUS_OVER_VOLTAGE = 7,
|
||||
BUS_ABNORMAL_VOLTAGE = 8,
|
||||
PHASE_OVER_VOLTAGE = 9,
|
||||
ID_NUMBER_REPETITION = 10,
|
||||
BUS_UNDER_VOLTAGE = 11,
|
||||
PHASE_LOSS = 12,
|
||||
PHASE_UNDER_VOLTAGE = 14,
|
||||
CAN_COMMUNICATION_FAULT = 16,
|
||||
DCDC_UNEVEN_CURRENT_SHARING = 17,
|
||||
PFC_POWER_OFF = 19,
|
||||
FAN_FULL_SPEED = 21,
|
||||
DCDC_POWER_OFF = 22,
|
||||
POWER_LIMITING = 23,
|
||||
TEMPERATURE_POWER_LIMITING = 24,
|
||||
AC_POWER_LIMITING = 25,
|
||||
DCDC_EEPROM_FAULTS = 26,
|
||||
FAN_FAULTS = 27,
|
||||
DCDC_SHORT_CIRCUIT = 28,
|
||||
PFC_EEPROM_FAULTS = 29,
|
||||
DCDC_OVER_TEMPERATURE = 30,
|
||||
DCDC_OUTPUT_OVER_VOLTAGE = 31,
|
||||
};
|
||||
|
||||
constexpr uint16_t MESSAGE_HEADER = 0b001100000;
|
||||
constexpr uint16_t MESSAGE_HEADER_MASK = 0b111111111;
|
||||
constexpr auto MESSAGE_HEADER_BIT_SHIFT = 20;
|
||||
constexpr auto MESSAGE_HEADER_PTP_BIT_SHIFT = 19;
|
||||
constexpr auto MESSAGE_HEADER_DSTADDR_BIT_SHIFT = 11;
|
||||
constexpr auto MESSAGE_HEADER_SRCADDR_BIT_SHIFT = 3;
|
||||
constexpr auto MESSAGE_HEADER_CNT_BIT_SHIFT = 2;
|
||||
|
||||
constexpr auto ERROR_FLAG_BIT_SHIFT = 7;
|
||||
|
||||
// FIXME (aw): unknown ValueTypes
|
||||
// CURRENT_ALARM_STATUS = 0x0040 (is this get or set?)
|
||||
// MODULE_GROUPING_SETTINGS = 0x0048 (is this get or set?)
|
||||
|
||||
} // namespace def
|
||||
|
||||
int dumb_function();
|
||||
|
||||
void set_header(struct can_frame&, uint8_t source, uint8_t destination = 0xFF);
|
||||
|
||||
void power_on(struct can_frame&, bool switch_on, bool close_input_relay);
|
||||
|
||||
void request_data(struct can_frame&, def::ReadValueType);
|
||||
|
||||
void set_data(struct can_frame&, def::SetValueType, const std::vector<uint8_t>& payload);
|
||||
|
||||
uint8_t parse_source(const struct can_frame&);
|
||||
uint16_t parse_msg_type(const struct can_frame&);
|
||||
|
||||
inline bool is_error_flag_set(const struct can_frame& frame) {
|
||||
return (frame.data[0] >> def::ERROR_FLAG_BIT_SHIFT);
|
||||
}
|
||||
|
||||
} // namespace can::protocol::dpm1000
|
||||
|
||||
#endif // CAN_PROTOCOL_DPM1000_HPP
|
||||
81
tools/EVerest-main/lib/everest/can_dpm1000/src/dpm1000.cpp
Normal file
81
tools/EVerest-main/lib/everest/can_dpm1000/src/dpm1000.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright Pionix GmbH and Contributors to EVerest
|
||||
#include <everest/can/protocol/dpm1000.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
namespace can::protocol::dpm1000 {
|
||||
|
||||
static inline void clear_frame_data(struct can_frame& frame) {
|
||||
memset(frame.data, 0, sizeof(frame.data));
|
||||
}
|
||||
|
||||
template <typename EnumType> static inline auto to_underlying(EnumType value) {
|
||||
return static_cast<std::underlying_type_t<EnumType>>(value);
|
||||
}
|
||||
|
||||
static void set_msg_type(def::MessageType msg_type, struct can_frame& frame) {
|
||||
frame.data[0] = to_underlying(msg_type);
|
||||
}
|
||||
|
||||
void set_header(struct can_frame& frame, uint8_t source, uint8_t destination) {
|
||||
const auto ptp_value = (destination != 0xFF);
|
||||
frame.can_id = (0b1UL << 31UL) | (def::MESSAGE_HEADER << def::MESSAGE_HEADER_BIT_SHIFT) |
|
||||
(ptp_value << def::MESSAGE_HEADER_PTP_BIT_SHIFT) |
|
||||
(destination << def::MESSAGE_HEADER_DSTADDR_BIT_SHIFT) |
|
||||
(source << def::MESSAGE_HEADER_SRCADDR_BIT_SHIFT) | (0 << def::MESSAGE_HEADER_CNT_BIT_SHIFT) |
|
||||
0b11; // bits 0 and 1 default to 1 ...
|
||||
frame.data[1] = to_underlying(def::ErrorType::NO_ERROR);
|
||||
}
|
||||
|
||||
void power_on(struct can_frame& frame, bool switch_on, bool close_input_relay) {
|
||||
clear_frame_data(frame);
|
||||
frame.data[0] = to_underlying(def::MessageType::SET_DATA_REQUEST);
|
||||
|
||||
frame.data[2] |= (((switch_on) ? 0 : 1) << def::SET_DATA_REQUEST_POWER_BIT_SHIFT);
|
||||
frame.data[2] |= (((close_input_relay) ? 0 : 1) << def::SET_DATA_REQUEST_INPUT_RELAY_BIT_SHIFT);
|
||||
frame.data[3] = 0x80; // FIXME (aw): literal
|
||||
frame.can_dlc = sizeof(frame.data);
|
||||
}
|
||||
|
||||
void request_data(struct can_frame& frame, def::ReadValueType value_type) {
|
||||
clear_frame_data(frame);
|
||||
frame.data[0] = to_underlying(def::MessageType::REQUEST_DATA_BYTE);
|
||||
|
||||
const auto value_type_raw = htobe16(to_underlying(value_type));
|
||||
memcpy(&frame.data[2], &value_type_raw, sizeof(value_type_raw));
|
||||
|
||||
frame.can_dlc = sizeof(frame.data);
|
||||
}
|
||||
|
||||
void set_data(struct can_frame& frame, def::SetValueType value_type, const std::vector<uint8_t>& payload) {
|
||||
clear_frame_data(frame);
|
||||
frame.data[0] = to_underlying(def::MessageType::SET_DATA);
|
||||
|
||||
const auto value_type_raw = htobe16(to_underlying(value_type));
|
||||
memcpy(&frame.data[2], &value_type_raw, sizeof(value_type_raw));
|
||||
|
||||
constexpr std::size_t MAX_PAYLOAD_SIZE = 4;
|
||||
const auto payload_size = std::min(payload.size(), MAX_PAYLOAD_SIZE);
|
||||
|
||||
memcpy(&frame.data[4], payload.data(), payload_size);
|
||||
|
||||
frame.can_dlc = sizeof(frame.data) - MAX_PAYLOAD_SIZE + payload_size;
|
||||
}
|
||||
|
||||
uint8_t parse_source(const struct can_frame& frame) {
|
||||
return ((frame.can_id >> def::MESSAGE_HEADER_SRCADDR_BIT_SHIFT) & 0xFF);
|
||||
}
|
||||
|
||||
uint16_t parse_msg_type(const struct can_frame& frame) {
|
||||
uint16_t retval;
|
||||
memcpy(&retval, &frame.data[2], sizeof(retval));
|
||||
|
||||
return be16toh(retval);
|
||||
}
|
||||
|
||||
} // namespace can::protocol::dpm1000
|
||||
@@ -0,0 +1,13 @@
|
||||
add_executable(dpm1000_tester)
|
||||
target_sources(dpm1000_tester
|
||||
PRIVATE
|
||||
dpm1000_tester.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(dpm1000_tester
|
||||
PRIVATE
|
||||
can_protocols::dpm1000
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
target_compile_features(dpm1000_tester PRIVATE cxx_std_17)
|
||||
@@ -0,0 +1,346 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright Pionix GmbH and Contributors to EVerest
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <poll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <everest/can/protocol/dpm1000.hpp>
|
||||
|
||||
namespace dpm1000 = can::protocol::dpm1000;
|
||||
|
||||
static void exit_with_error(const char* msg) {
|
||||
fprintf(stderr, "%s (%s)\n", msg, strerror(errno));
|
||||
exit(-EXIT_FAILURE);
|
||||
}
|
||||
|
||||
template <typename EnumType> static inline auto to_underlying(EnumType value) {
|
||||
return static_cast<std::underlying_type_t<EnumType>>(value);
|
||||
}
|
||||
|
||||
struct CanRequest {
|
||||
enum class State {
|
||||
IDLE,
|
||||
ISSUED,
|
||||
COMPLETED,
|
||||
FAILED,
|
||||
} state{State::IDLE};
|
||||
|
||||
uint16_t msg_type;
|
||||
std::array<uint8_t, 4> response;
|
||||
std::condition_variable cv;
|
||||
std::mutex mutex;
|
||||
};
|
||||
|
||||
class CanBroker {
|
||||
public:
|
||||
enum class AccessReturnType {
|
||||
SUCCESS,
|
||||
FAILED,
|
||||
TIMEOUT,
|
||||
NOT_READY,
|
||||
};
|
||||
CanBroker(const std::string& interface_name);
|
||||
|
||||
AccessReturnType read_data(dpm1000::def::ReadValueType, float& result);
|
||||
AccessReturnType set_data(dpm1000::def::SetValueType, float value);
|
||||
void enable();
|
||||
|
||||
~CanBroker();
|
||||
|
||||
private:
|
||||
constexpr static auto ACCESS_TIMEOUT = std::chrono::milliseconds(250);
|
||||
void loop();
|
||||
|
||||
void write_to_can(const struct can_frame& frame);
|
||||
AccessReturnType dispatch_frame(const struct can_frame& frame, uint16_t id, uint32_t* result = nullptr);
|
||||
|
||||
void handle_can_input(const struct can_frame& frame);
|
||||
|
||||
bool device_found{false};
|
||||
uint8_t device_src;
|
||||
|
||||
std::mutex access_mtx;
|
||||
CanRequest request;
|
||||
|
||||
const uint8_t monitor_id{0xf0};
|
||||
|
||||
std::thread loop_thread;
|
||||
|
||||
int event_fd{-1};
|
||||
int can_fd{-1};
|
||||
};
|
||||
|
||||
CanBroker::CanBroker(const std::string& interface_name) {
|
||||
can_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
|
||||
if (can_fd == -1) {
|
||||
exit_with_error("Failed to open socket");
|
||||
}
|
||||
|
||||
// retrieve interface index from interface name
|
||||
struct ifreq ifr;
|
||||
|
||||
if (interface_name.size() >= sizeof(ifr.ifr_name)) {
|
||||
exit_with_error("Interface name too long.");
|
||||
} else {
|
||||
strcpy(ifr.ifr_name, interface_name.c_str());
|
||||
}
|
||||
|
||||
if (ioctl(can_fd, SIOCGIFINDEX, &ifr) == -1) {
|
||||
exit_with_error("Failed with ioctl/SIOCGIFINDEX");
|
||||
}
|
||||
|
||||
// bind to the interface
|
||||
struct sockaddr_can addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
if (bind(can_fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == -1) {
|
||||
exit_with_error("Failed with bind");
|
||||
}
|
||||
|
||||
event_fd = eventfd(0, 0);
|
||||
|
||||
loop_thread = std::thread(&CanBroker::loop, this);
|
||||
}
|
||||
|
||||
CanBroker::~CanBroker() {
|
||||
uint64_t quit_value = 1;
|
||||
write(event_fd, &quit_value, sizeof(quit_value));
|
||||
|
||||
loop_thread.join();
|
||||
|
||||
close(can_fd);
|
||||
close(event_fd);
|
||||
}
|
||||
|
||||
void CanBroker::loop() {
|
||||
std::array<struct pollfd, 2> pollfds = {{
|
||||
{can_fd, POLLIN, 0},
|
||||
{event_fd, POLLIN, 0},
|
||||
}};
|
||||
|
||||
while (true) {
|
||||
const auto poll_result = poll(pollfds.data(), pollfds.size(), -1);
|
||||
|
||||
if (poll_result == 0) {
|
||||
// timeout
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pollfds[0].revents & POLLIN) {
|
||||
struct can_frame frame;
|
||||
read(can_fd, &frame, sizeof(frame));
|
||||
|
||||
if (device_found) {
|
||||
handle_can_input(frame);
|
||||
} else {
|
||||
device_src = dpm1000::parse_source(frame);
|
||||
device_found = true;
|
||||
printf("Found device with source number %02X\n", device_src);
|
||||
}
|
||||
}
|
||||
|
||||
if (pollfds[1].revents & POLLIN) {
|
||||
uint64_t tmp;
|
||||
read(event_fd, &tmp, sizeof(tmp));
|
||||
// new event, for now, we do not care, later on we could check, if it is an exit event code
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CanBroker::enable() {
|
||||
struct can_frame frame;
|
||||
dpm1000::power_on(frame, true, true);
|
||||
dpm1000::set_header(frame, monitor_id, device_src);
|
||||
|
||||
write_to_can(frame);
|
||||
}
|
||||
|
||||
CanBroker::AccessReturnType CanBroker::dispatch_frame(const struct can_frame& frame, uint16_t id,
|
||||
uint32_t* return_payload) {
|
||||
if (not device_found) {
|
||||
return AccessReturnType::NOT_READY;
|
||||
}
|
||||
|
||||
// wait until we get access
|
||||
std::lock_guard<std::mutex> access_lock(access_mtx);
|
||||
|
||||
std::unique_lock<std::mutex> request_lock(request.mutex);
|
||||
write_to_can(frame);
|
||||
request.msg_type = id;
|
||||
request.state = CanRequest::State::ISSUED;
|
||||
|
||||
const auto finished = request.cv.wait_for(request_lock, ACCESS_TIMEOUT,
|
||||
[this]() { return request.state != CanRequest::State::ISSUED; });
|
||||
|
||||
if (not finished) {
|
||||
return AccessReturnType::TIMEOUT;
|
||||
}
|
||||
|
||||
if (request.state == CanRequest::State::FAILED) {
|
||||
return AccessReturnType::FAILED;
|
||||
}
|
||||
|
||||
// success
|
||||
if (return_payload) {
|
||||
memcpy(return_payload, request.response.data(), sizeof(std::remove_pointer_t<decltype(return_payload)>));
|
||||
}
|
||||
|
||||
return AccessReturnType::SUCCESS;
|
||||
}
|
||||
|
||||
CanBroker::AccessReturnType CanBroker::read_data(dpm1000::def::ReadValueType value_type, float& result) {
|
||||
const auto id = static_cast<std::underlying_type_t<decltype(value_type)>>(value_type);
|
||||
|
||||
struct can_frame frame;
|
||||
dpm1000::request_data(frame, value_type);
|
||||
dpm1000::set_header(frame, monitor_id, device_src);
|
||||
|
||||
uint32_t tmp;
|
||||
const auto status = dispatch_frame(frame, id, &tmp);
|
||||
|
||||
if (status == AccessReturnType::SUCCESS) {
|
||||
memcpy(&result, &tmp, sizeof(result));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
CanBroker::AccessReturnType CanBroker::set_data(dpm1000::def::SetValueType value_type, float payload) {
|
||||
const auto id = static_cast<std::underlying_type_t<decltype(value_type)>>(value_type);
|
||||
|
||||
uint8_t raw_payload[sizeof(payload)];
|
||||
memcpy(raw_payload, &payload, sizeof(payload));
|
||||
|
||||
struct can_frame frame;
|
||||
dpm1000::set_data(frame, value_type, {raw_payload[3], raw_payload[2], raw_payload[1], raw_payload[0]});
|
||||
dpm1000::set_header(frame, monitor_id, device_src);
|
||||
|
||||
return dispatch_frame(frame, id);
|
||||
}
|
||||
|
||||
void CanBroker::write_to_can(const struct can_frame& frame) {
|
||||
write(can_fd, &frame, sizeof(frame));
|
||||
}
|
||||
|
||||
void CanBroker::handle_can_input(const struct can_frame& frame) {
|
||||
if (((frame.can_id >> dpm1000::def::MESSAGE_HEADER_BIT_SHIFT) & dpm1000::def::MESSAGE_HEADER_MASK) !=
|
||||
dpm1000::def::MESSAGE_HEADER) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> request_lock(request.mutex);
|
||||
if ((request.state != CanRequest::State::ISSUED) or (request.msg_type != dpm1000::parse_msg_type(frame))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dpm1000::is_error_flag_set(frame)) {
|
||||
request.state = CanRequest::State::FAILED;
|
||||
} else {
|
||||
// this is ugly
|
||||
for (auto i = 0; i < request.response.size(); ++i) {
|
||||
request.response[i] = frame.data[7 - i];
|
||||
}
|
||||
request.state = CanRequest::State::COMPLETED;
|
||||
}
|
||||
|
||||
request_lock.unlock();
|
||||
request.cv.notify_one();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
struct can_frame frame;
|
||||
|
||||
CanBroker broker("can0");
|
||||
float result;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
broker.enable();
|
||||
|
||||
// voltage 300 - 1000
|
||||
// current 0 - 2
|
||||
|
||||
// while (1) {
|
||||
auto success = broker.set_data(dpm1000::def::SetValueType::VOLTAGE, 1000);
|
||||
printf("Voltage setting success: %d\n", to_underlying(success));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
success = broker.set_data(dpm1000::def::SetValueType::CURRENT_LIMIT, 0);
|
||||
printf("Current setting success: %d\n", to_underlying(success));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
// }
|
||||
|
||||
broker.read_data(dpm1000::def::ReadValueType::VOLTAGE_LIMIT, result);
|
||||
printf("Upper limit point voltage: %f\n", result);
|
||||
|
||||
broker.read_data(dpm1000::def::ReadValueType::CURRENT_LIMIT, result);
|
||||
printf("Current limit: %f\n", result);
|
||||
|
||||
broker.read_data(dpm1000::def::ReadValueType::VOLTAGE, result);
|
||||
printf("Default Voltage: %f\n", result);
|
||||
|
||||
broker.read_data(dpm1000::def::ReadValueType::ENV_TEMPERATURE, result);
|
||||
printf("Env temp: %f\n", result);
|
||||
|
||||
broker.read_data(dpm1000::def::ReadValueType::CURRENT, result);
|
||||
printf("Current: %f\n", result);
|
||||
|
||||
broker.read_data(dpm1000::def::ReadValueType::VOLTAGE, result);
|
||||
printf("Voltage: %f\n", result);
|
||||
|
||||
broker.read_data(dpm1000::def::ReadValueType::AC_VOLTAGE_PHASE_A, result);
|
||||
printf("Voltage PH1: %f\n", result);
|
||||
broker.read_data(dpm1000::def::ReadValueType::AC_VOLTAGE_PHASE_B, result);
|
||||
printf("Voltage PH2: %f\n", result);
|
||||
broker.read_data(dpm1000::def::ReadValueType::AC_VOLTAGE_PHASE_C, result);
|
||||
printf("Voltage PH3: %f\n", result);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
return 0;
|
||||
|
||||
// dpm1000::power_on(frame, false, false);
|
||||
dpm1000::request_data(frame, dpm1000::def::ReadValueType::CURRENT_LIMIT);
|
||||
// dpm1000::set_data(frame, dpm1000::def::SetValueType::CURRENT_LIMIT, {0x23, 0x24});
|
||||
dpm1000::set_header(frame, 0xf0, 0b00000100);
|
||||
|
||||
printf("frame is %08X#", frame.can_id);
|
||||
for (auto i = 0; i < sizeof(frame.data); ++i) {
|
||||
printf("%02X", frame.data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
printf("frame length: %d\n", frame.can_dlc);
|
||||
|
||||
float foo = 5.0;
|
||||
uint32_t bar;
|
||||
memcpy(&bar, &foo, sizeof(foo));
|
||||
printf("float repr is %08lX\n", (unsigned long)bar);
|
||||
// printf("Answer is %d\n", dpm1000::dumb_function());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// can0 07078023 [8] 01 F0 10 00 00 00 00 00
|
||||
// 0b1110000 | 0 | 11110000 | 00000100 | 011
|
||||
|
||||
// 0607FF83
|
||||
// 0b1100000 | 0 | 11111111 | 11110000 | 011
|
||||
|
||||
// request: 0b1000 | 01100000 | 1 | 00000100 | 11110000 | 011
|
||||
|
||||
// 060F8023 [8] C1 F2 03 00 00 00 00 00 -> error bit, response request,
|
||||
// 0b1100000 | 1 | 11110000 | 00000100 | 011
|
||||
// can0 07078023 [8] 02 F0 01 00 00 00 00 00
|
||||
Reference in New Issue
Block a user