├── Loadcell-hx711.png ├── Pro micro - HX711.jpg ├── LICENSE ├── Gamepad.h ├── HX711-multi.h ├── VNPedal.ino ├── HID.h ├── Gamepad.cpp ├── HID.cpp └── HX711-multi.cpp /Loadcell-hx711.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoantv/VNPedal/HEAD/Loadcell-hx711.png -------------------------------------------------------------------------------- /Pro micro - HX711.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoantv/VNPedal/HEAD/Pro micro - HX711.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 hoantv 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Gamepad.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015 NicoHood 3 | Copyright (c) 2019 HoanTV 4 | See the readme for credit to other people. 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | */ 21 | #ifndef GAMEPAD_h 22 | #define GAMEPAD_h 23 | 24 | #include "HID.h" 25 | 26 | #if !defined(_USING_HID) 27 | 28 | #warning "Using legacy HID core (non pluggable)" 29 | 30 | #else 31 | 32 | 33 | typedef struct 34 | { //WheelReport 35 | uint8_t buttons = 0x00; 36 | int32_t xAxis; 37 | int32_t yAxis; 38 | int32_t zAxis; 39 | int32_t rxAxis; 40 | int32_t ryAxis; 41 | int32_t rzAxis; 42 | } GamepadReport; 43 | 44 | class Gamepad 45 | { 46 | private: 47 | GamepadReport gamepadReport; 48 | void SendReport(void* data, int len); 49 | 50 | public: 51 | Gamepad(void); 52 | 53 | void begin(void); 54 | void end(void); 55 | void write(void); 56 | void press(uint8_t b); 57 | void release(uint8_t b); 58 | void releaseAll(void); 59 | void buttons(uint8_t b); 60 | 61 | void xAxis(int32_t a); 62 | void yAxis(int32_t a); 63 | void zAxis(int32_t a); 64 | void rxAxis(int32_t a); 65 | void ryAxis(int32_t a); 66 | void rzAxis(int32_t a); 67 | }; 68 | 69 | #endif 70 | #endif 71 | -------------------------------------------------------------------------------- /HX711-multi.h: -------------------------------------------------------------------------------- 1 | #ifndef HX711_MULTI_h 2 | #define HX711_MULTI_h 3 | 4 | #if ARDUINO >= 100 5 | #include "Arduino.h" 6 | #else 7 | #include "WProgram.h" 8 | #endif 9 | 10 | class HX711MULTI { 11 | private: 12 | byte PD_SCK; // Power Down and Serial Clock Input Pin 13 | byte COUNT; // The number of channels to read 14 | byte *DOUT; // Serial Data Output Pin 15 | byte GAIN; // amplification factor 16 | 17 | bool debugEnabled; //print debug messages? 18 | 19 | long *OFFSETS; // used for tare weight 20 | float *SCALES; // used to return weight in grams, kg, ounces, whatever 21 | 22 | public: 23 | // define clock and data pin, channel, and gain factor 24 | // channel selection is made by passing the appropriate gain: 128 or 64 for channel A, 32 for channel B 25 | // count: the number of channels 26 | // dout: an array of pin numbers, of length 'count', one entry per channel 27 | HX711MULTI(int count, byte *dout, byte pd_sck, byte gain = 128); 28 | 29 | virtual ~HX711MULTI(); 30 | 31 | //returns the number of channels 32 | byte get_count(); 33 | 34 | // check if HX711 is ready 35 | // from the datasheet: When output data is not ready for retrieval, digital output pin DOUT is high. Serial clock 36 | // input PD_SCK should be low. When DOUT goes to low, it indicates data is ready for retrieval. 37 | bool is_ready(); 38 | 39 | // set the gain factor; takes effect only after a call to read() 40 | // channel A can be set for a 128 or 64 gain; channel B has a fixed 32 gain 41 | // depending on the parameter, the channel is also set to either A or B 42 | void set_gain(byte gain = 128); 43 | 44 | // waits for the chip to be ready and returns a reading 45 | void read(long *result = NULL); 46 | 47 | // same as read, but does not offset the values according to the tare 48 | void readRaw(long *result = NULL); 49 | 50 | // set the OFFSET value for tare weight 51 | // times: how many times to read the tare value 52 | // returns true iff the offsets have been reset for the scale during this call. 53 | // tolerance: the maximum deviation of samples, above which to reject the attempt to tare. (if set to 0, ignored) 54 | bool tare(byte times = 10, uint16_t tolerance = 0); 55 | 56 | // puts the chip into power down mode 57 | void power_down(); 58 | 59 | // wakes up the chip after power down mode 60 | void power_up(); 61 | 62 | void setDebugEnable(bool debugEnable = true); 63 | 64 | // NEW FEATURES 65 | float* get_scales(); 66 | void set_scales(float *_scales); 67 | void get_units(double *result = NULL); 68 | 69 | }; 70 | #endif /* HX711_MULTI_h */ 71 | -------------------------------------------------------------------------------- /VNPedal.ino: -------------------------------------------------------------------------------- 1 | #include "Gamepad.h" 2 | #include "HX711-multi.h" 3 | 4 | Gamepad gamepad; 5 | #define BAUD_RATE 9600 6 | 7 | // Pins to the load cell amp 8 | #define CLK 2 // clock pin to the load cell amps 9 | #define DOUT1 3 // data pin to the first lca 10 | #define DOUT2 4 // data pin to the second lca 11 | #define DOUT3 5 // data pin to the third lca 12 | 13 | #define TARE_TIMEOUT_SECONDS 4 14 | 15 | byte DOUTS[3] = {DOUT1, DOUT2, DOUT3}; 16 | 17 | #define CHANNEL_COUNT sizeof(DOUTS)/sizeof(byte) 18 | 19 | long int results[CHANNEL_COUNT]; 20 | 21 | HX711MULTI scales(CHANNEL_COUNT, DOUTS, CLK); 22 | int32_t gas = 0 ; 23 | int32_t brake = 0; 24 | int32_t clutch = 0; 25 | 26 | const long SERIAL_REFRESH_TIME = 100; 27 | long refresh_time; 28 | 29 | //XY shifter use potentiometer 30 | uint16_t x = A0; 31 | uint16_t y = A1; 32 | uint8_t shifterValue = 0; 33 | 34 | 35 | void setup() { 36 | Serial.begin(BAUD_RATE); 37 | gamepad.begin(); 38 | tare(); 39 | } 40 | 41 | void loop() { 42 | // release all previos value of gamepad 43 | gamepad.releaseAll(); 44 | shifterValue = calculatedShifter(mappedX(analogRead(x)), mappedY(analogRead(y)), shifterValue); 45 | gamepad.press(shifterValue+1); 46 | scales.read(results); 47 | results[0] = constrain(results[0] * (-1), 0, 300000); // *(-1) and 300000 are based on the loadcell value. 48 | results[1] = constrain(results[1], 0, 1048576); 49 | results[2] = constrain(results[2] * (-1), 0, 500000); 50 | gas = convert(results[0], 0, 300000, 0, 1048576); 51 | brake = results[1]; 52 | clutch = convert(results[2], 0, 500000, 0, 1048576); 53 | gamepad.rxAxis((gas)); 54 | gamepad.ryAxis((brake)); 55 | gamepad.rzAxis((clutch)); 56 | 57 | gamepad.write(); 58 | delay(10); 59 | 60 | //on serial data (any data) re-tare 61 | if (Serial.available() > 0) { 62 | while (Serial.available()) { 63 | Serial.read(); 64 | } 65 | tare(); 66 | } 67 | 68 | } 69 | 70 | void tare() { 71 | bool tareSuccessful = false; 72 | unsigned long tareStartTime = millis(); 73 | while (!tareSuccessful && millis() < (tareStartTime + TARE_TIMEOUT_SECONDS * 1000)) { 74 | tareSuccessful = scales.tare(20, 10000); //reject 'tare' if still ringing 75 | } 76 | } 77 | 78 | long convert(long input, long minInput, long maxInput, long minOutput, long maxOutput) { 79 | float ratio = ((float)input - (float)minInput) / ((float)maxInput - (float)minInput); 80 | float result = minOutput + (maxOutput - minOutput) * ratio; 81 | return (long) result; 82 | } 83 | 84 | uint8_t mappedX(uint16_t x) { 85 | if ( x > 540) { 86 | return 0; 87 | } else if (x < 530 && x > 510) { 88 | return 1; 89 | } 90 | else if (x < 490 && x > 470) { 91 | return 2; 92 | } else if (x < 460) { 93 | return 3; 94 | } 95 | else { 96 | return 4; 97 | } 98 | } 99 | 100 | uint8_t mappedY(uint16_t y) { 101 | if ( y < 470) { 102 | return 0; 103 | } else if (y > 550) { 104 | return 2; 105 | } 106 | else { 107 | return 1; 108 | } 109 | } 110 | uint8_t calculatedShifter(uint8_t x, uint8_t y, uint8_t shifter) { 111 | if (x == 0 && y == 0) { 112 | return 1; 113 | } else if (x == 0 && y == 2) { 114 | return 2; 115 | } else if (x == 1 && y == 0) { 116 | return 3; 117 | } 118 | else if (x == 1 && y == 2) { 119 | return 4; 120 | } 121 | else if (x == 2 && y == 0) { 122 | return 5; 123 | } 124 | else if (x == 2 && y == 2) { 125 | return 6; 126 | } 127 | else if (x == 3 && y == 2) { 128 | return 7; 129 | } else if (x == 1 && y == 1) { 130 | return 0; 131 | } 132 | else { 133 | return shifter; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /HID.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Arduino LLC 3 | Original code (pre-library): Copyright (c) 2011, Peter Barrett 4 | 5 | Permission to use, copy, modify, and/or distribute this software for 6 | any purpose with or without fee is hereby granted, provided that the 7 | above copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 12 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES 13 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 14 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 15 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 16 | SOFTWARE. 17 | */ 18 | 19 | #ifndef HID_h 20 | #define HID_h 21 | 22 | #include 23 | #include 24 | #include "PluggableUSB.h" 25 | 26 | #if defined(USBCON) 27 | 28 | #define _USING_HID 29 | 30 | // HID 'Driver' 31 | // ------------ 32 | #define HID_GET_REPORT 0x01 33 | #define HID_GET_IDLE 0x02 34 | #define HID_GET_PROTOCOL 0x03 35 | #define HID_SET_REPORT 0x09 36 | #define HID_SET_IDLE 0x0A 37 | #define HID_SET_PROTOCOL 0x0B 38 | 39 | #define HID_HID_DESCRIPTOR_TYPE 0x21 40 | #define HID_REPORT_DESCRIPTOR_TYPE 0x22 41 | #define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 42 | 43 | // HID subclass HID1.11 Page 8 4.2 Subclass 44 | #define HID_SUBCLASS_NONE 0 45 | #define HID_SUBCLASS_BOOT_INTERFACE 1 46 | 47 | // HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols 48 | #define HID_PROTOCOL_NONE 0 49 | #define HID_PROTOCOL_KEYBOARD 1 50 | #define HID_PROTOCOL_MOUSE 2 51 | 52 | // Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request 53 | // "protocol" variable is used for this purpose. 54 | #define HID_BOOT_PROTOCOL 0 55 | #define HID_REPORT_PROTOCOL 1 56 | 57 | // HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request 58 | #define HID_REPORT_TYPE_INPUT 1 59 | #define HID_REPORT_TYPE_OUTPUT 2 60 | #define HID_REPORT_TYPE_FEATURE 3 61 | 62 | typedef struct 63 | { 64 | uint8_t len; // 9 65 | uint8_t dtype; // 0x21 66 | uint8_t addr; 67 | uint8_t versionL; // 0x101 68 | uint8_t versionH; // 0x101 69 | uint8_t country; 70 | uint8_t desctype; // 0x22 report 71 | uint8_t descLenL; 72 | uint8_t descLenH; 73 | } HIDDescDescriptor; 74 | 75 | typedef struct 76 | { 77 | InterfaceDescriptor hid; 78 | HIDDescDescriptor desc; 79 | EndpointDescriptor in; 80 | } HIDDescriptor; 81 | 82 | class HIDSubDescriptor { 83 | public: 84 | HIDSubDescriptor *next = NULL; 85 | HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } 86 | 87 | const void* data; 88 | const uint16_t length; 89 | }; 90 | 91 | class HID_ : public PluggableUSBModule 92 | { 93 | public: 94 | HID_(void); 95 | int begin(void); 96 | int SendReport(uint8_t id, const void* data, int len); 97 | void AppendDescriptor(HIDSubDescriptor* node); 98 | 99 | protected: 100 | // Implementation of the PluggableUSBModule 101 | int getInterface(uint8_t* interfaceCount); 102 | int getDescriptor(USBSetup& setup); 103 | bool setup(USBSetup& setup); 104 | uint8_t getShortName(char* name); 105 | 106 | private: 107 | uint8_t epType[1]; 108 | 109 | HIDSubDescriptor* rootNode; 110 | uint16_t descriptorSize; 111 | 112 | uint8_t protocol; 113 | uint8_t idle; 114 | }; 115 | 116 | // Replacement for global singleton. 117 | // This function prevents static-initialization-order-fiasco 118 | // https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use 119 | HID_& HID(); 120 | 121 | #define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } 122 | 123 | #endif // USBCON 124 | 125 | #endif // HID_h 126 | -------------------------------------------------------------------------------- /Gamepad.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015 NicoHood 3 | Copyright (c) 2019 HoanTV 4 | See the readme for credit to other people. 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | */ 21 | #include "Gamepad.h" 22 | #define HID_REPORTID_GAMEPAD 0x01 23 | static const uint8_t _hidReportDescriptor[] PROGMEM = { 24 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 25 | 0x09, 0x04, // USAGE (Joystick) 26 | 0xA1, 0x01, // COLLECTION (Application) 27 | //================================Input Report======================================// 28 | 0x09, 0x01, // USAGE (Pointer) 29 | // WheelReport 30 | 0x85, HID_REPORTID_GAMEPAD, // REPORT_ID (1) 31 | 0xA1, 0x00, // COLLECTION (Physical) 32 | // Button for Shifter 33 | 0x05, 0x09, // USAGE_PAGE (Button) 34 | 0x19, 0x01, // USAGE_MINIMUM (Button 1) 35 | 0x29, 0x08, // USAGE_MAXIMUM (Button 8) 36 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 37 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) 38 | 0x75, 0x01, // REPORT_SIZE (1) 39 | 0x95, 0x08, // REPORT_COUNT (8) 40 | 0x81, 0x02, //INPUT (Data,Var,Abs) 41 | //6 Axis for steering wheel, accelerator, brake, clutch, handbrake and spare 42 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 43 | 0xa1, 0x00, // COLLECTION (Physical) 44 | 0x09, 0x30, // USAGE (X) 45 | 0x09, 0x31, // USAGE (Y) 46 | 0x09, 0x32, // USAGE (Z) 47 | 0x09, 0x33, // USAGE (Rx) 48 | 0x09, 0x34, // USAGE (Ry) 49 | 0x09, 0x35, // USAGE (Rz) */ 50 | 0x15, 0x00, //LOGICAL_MINIMUM (0) 51 | 0x27, 0x00, 0x00, 0x10,0x00, //LOGICAL_MAXIMUM (104856) 52 | 0x75, 0x20, // REPORT_SIZE (32) 53 | 0x95, 0x06, // REPORT_COUNT (6) 54 | 0x81, 0x02, // INPUT (Data,Var,Abs) 55 | 0xc0, // END_COLLECTION */ 56 | 0xc0, // END_COLLECTION */ 57 | 58 | 0xC0, // END COLLECTION () 59 | }; 60 | 61 | 62 | Gamepad::Gamepad(void) 63 | { 64 | static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor)); 65 | HID().AppendDescriptor(&node); 66 | } 67 | 68 | void Gamepad::SendReport(void* data, int length) { 69 | HID().SendReport(HID_REPORTID_GAMEPAD, data, length); 70 | } 71 | 72 | void Gamepad::begin(void) { 73 | // release all buttons 74 | end(); 75 | } 76 | 77 | void Gamepad::end(void) { 78 | memset(&gamepadReport, 0x00, sizeof(gamepadReport)); 79 | SendReport(&gamepadReport, sizeof(gamepadReport)); 80 | } 81 | 82 | 83 | void Gamepad::write(void) { 84 | SendReport(&gamepadReport, sizeof(gamepadReport)); 85 | } 86 | 87 | 88 | void Gamepad::press(uint8_t b) { 89 | gamepadReport.buttons |= (uint8_t)1 << (b - 1); 90 | } 91 | 92 | 93 | void Gamepad::release(uint8_t b) { 94 | gamepadReport.buttons &= ~((uint8_t)1 << (b - 1)); 95 | } 96 | 97 | 98 | void Gamepad::releaseAll(void) { 99 | memset(&gamepadReport, 0x00, sizeof(gamepadReport)); 100 | } 101 | 102 | void Gamepad::buttons(uint8_t b) { 103 | gamepadReport.buttons = b; 104 | } 105 | 106 | void Gamepad::xAxis(int32_t a) { 107 | gamepadReport.xAxis = a; 108 | } 109 | void Gamepad::yAxis(int32_t a) { 110 | gamepadReport.yAxis = a; 111 | } 112 | void Gamepad::zAxis(int32_t a) { 113 | gamepadReport.zAxis = a; 114 | } 115 | void Gamepad::rxAxis(int32_t a) { 116 | gamepadReport.rxAxis = a; 117 | } 118 | void Gamepad::ryAxis(int32_t a) { 119 | gamepadReport.ryAxis = a; 120 | } 121 | void Gamepad::rzAxis(int32_t a) { 122 | gamepadReport.rzAxis = a; 123 | } 124 | -------------------------------------------------------------------------------- /HID.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Arduino LLC 3 | Original code (pre-library): Copyright (c) 2011, Peter Barrett 4 | 5 | Permission to use, copy, modify, and/or distribute this software for 6 | any purpose with or without fee is hereby granted, provided that the 7 | above copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 12 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES 13 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 14 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 15 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 16 | SOFTWARE. 17 | */ 18 | 19 | #include "HID.h" 20 | 21 | #if defined(USBCON) 22 | 23 | HID_& HID() 24 | { 25 | static HID_ obj; 26 | return obj; 27 | } 28 | 29 | int HID_::getInterface(uint8_t* interfaceCount) 30 | { 31 | *interfaceCount += 1; // uses 1 32 | HIDDescriptor hidInterface = { 33 | D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), 34 | D_HIDREPORT(descriptorSize), 35 | D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) 36 | }; 37 | return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); 38 | } 39 | 40 | int HID_::getDescriptor(USBSetup& setup) 41 | { 42 | // Check if this is a HID Class Descriptor request 43 | if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } 44 | if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } 45 | 46 | // In a HID Class Descriptor wIndex cointains the interface number 47 | if (setup.wIndex != pluggedInterface) { return 0; } 48 | 49 | int total = 0; 50 | HIDSubDescriptor* node; 51 | for (node = rootNode; node; node = node->next) { 52 | int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); 53 | if (res == -1) 54 | return -1; 55 | total += res; 56 | } 57 | 58 | // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol 59 | // due to the USB specs, but Windows and Linux just assumes its in report mode. 60 | protocol = HID_REPORT_PROTOCOL; 61 | 62 | return total; 63 | } 64 | 65 | uint8_t HID_::getShortName(char *name) 66 | { 67 | name[0] = 'H'; 68 | name[1] = 'I'; 69 | name[2] = 'D'; 70 | name[3] = 'A' + (descriptorSize & 0x0F); 71 | name[4] = 'A' + ((descriptorSize >> 4) & 0x0F); 72 | return 5; 73 | } 74 | 75 | void HID_::AppendDescriptor(HIDSubDescriptor *node) 76 | { 77 | if (!rootNode) { 78 | rootNode = node; 79 | } else { 80 | HIDSubDescriptor *current = rootNode; 81 | while (current->next) { 82 | current = current->next; 83 | } 84 | current->next = node; 85 | } 86 | descriptorSize += node->length; 87 | } 88 | 89 | int HID_::SendReport(uint8_t id, const void* data, int len) 90 | { 91 | auto ret = USB_Send(pluggedEndpoint, &id, 1); 92 | if (ret < 0) return ret; 93 | auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); 94 | if (ret2 < 0) return ret2; 95 | return ret + ret2; 96 | } 97 | 98 | bool HID_::setup(USBSetup& setup) 99 | { 100 | if (pluggedInterface != setup.wIndex) { 101 | return false; 102 | } 103 | 104 | uint8_t request = setup.bRequest; 105 | uint8_t requestType = setup.bmRequestType; 106 | 107 | if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) 108 | { 109 | if (request == HID_GET_REPORT) { 110 | // TODO: HID_GetReport(); 111 | return true; 112 | } 113 | if (request == HID_GET_PROTOCOL) { 114 | // TODO: Send8(protocol); 115 | return true; 116 | } 117 | if (request == HID_GET_IDLE) { 118 | // TODO: Send8(idle); 119 | } 120 | } 121 | 122 | if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) 123 | { 124 | if (request == HID_SET_PROTOCOL) { 125 | // The USB Host tells us if we are in boot or report mode. 126 | // This only works with a real boot compatible device. 127 | protocol = setup.wValueL; 128 | return true; 129 | } 130 | if (request == HID_SET_IDLE) { 131 | idle = setup.wValueL; 132 | return true; 133 | } 134 | if (request == HID_SET_REPORT) 135 | { 136 | //uint8_t reportID = setup.wValueL; 137 | //uint16_t length = setup.wLength; 138 | //uint8_t data[length]; 139 | // Make sure to not read more data than USB_EP_SIZE. 140 | // You can read multiple times through a loop. 141 | // The first byte (may!) contain the reportID on a multreport. 142 | //USB_RecvControl(data, length); 143 | } 144 | } 145 | 146 | return false; 147 | } 148 | 149 | HID_::HID_(void) : PluggableUSBModule(1, 1, epType), 150 | rootNode(NULL), descriptorSize(0), 151 | protocol(HID_REPORT_PROTOCOL), idle(1) 152 | { 153 | epType[0] = EP_TYPE_INTERRUPT_IN; 154 | PluggableUSB().plug(this); 155 | } 156 | 157 | int HID_::begin(void) 158 | { 159 | return 0; 160 | } 161 | 162 | #endif /* if defined(USBCON) */ 163 | -------------------------------------------------------------------------------- /HX711-multi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "HX711-multi.h" 3 | 4 | HX711MULTI::HX711MULTI(int count, byte *dout, byte pd_sck, byte gain) { 5 | PD_SCK = pd_sck; 6 | DOUT = dout; //TODO - make the input of dout to the function a const, or otherwise copy the values for local storage 7 | COUNT = count; 8 | 9 | debugEnabled = false; 10 | 11 | pinMode(PD_SCK, OUTPUT); 12 | for (int i=0; imaxValues[j]) { 93 | maxValues[j]=values[j]; 94 | } 95 | } 96 | } 97 | 98 | if (tolerance!=0 && times>1) { 99 | for (i=0; itolerance) { 101 | //one of the cells fluctuated more than the allowed tolerance, reject tare attempt; 102 | if (debugEnabled) { 103 | Serial.print("Rejecting tare: ("); 104 | Serial.print(i); 105 | Serial.print(") "); 106 | Serial.println(abs(maxValues[i]-minValues[i])); 107 | } 108 | return false; 109 | } 110 | } 111 | } 112 | 113 | //set the offsets 114 | for (i=0; i