Simple test application for the STMicroelectronics X-NUCLEO-IHM02A1 Stepper Motor Control Expansion Board.

Dependencies:   X_NUCLEO_IHM02A1 mbed

Fork of HelloWorld_IHM02A1 by ST Expansion SW Team

Motor Control with the X-NUCLEO-IHM02A1 Expansion Board

This application provides a simple example of usage of the X-NUCLEO-IHM02A1 Stepper Motor Control Expansion Board.
It shows how to use two stepper motors connected in daisy chain configuration to the board, moving the rotors to specific positions, with given speed values, direction of rotations, etc.

Committer:
Davidroid
Date:
Wed Nov 25 12:00:34 2015 +0000
Revision:
1:9f1974b0960d
Parent:
0:5148e9486cf2
Child:
2:41eeee48951b
+ Updated according to the StepperMotor's APIs.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Davidroid 0:5148e9486cf2 1 /**
Davidroid 0:5148e9486cf2 2 ******************************************************************************
Davidroid 0:5148e9486cf2 3 * @file main.cpp
Davidroid 0:5148e9486cf2 4 * @author Davide Aliprandi / AST
Davidroid 0:5148e9486cf2 5 * @version V1.0.0
Davidroid 0:5148e9486cf2 6 * @date November 4th, 2015
Davidroid 1:9f1974b0960d 7 * @brief mbed test application for the STMicrolectronics X-NUCLEO-IHM02A1
Davidroid 1:9f1974b0960d 8 * Motor Control Expansion Board: control of 2 motors.
Davidroid 0:5148e9486cf2 9 ******************************************************************************
Davidroid 0:5148e9486cf2 10 * @attention
Davidroid 0:5148e9486cf2 11 *
Davidroid 0:5148e9486cf2 12 * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
Davidroid 0:5148e9486cf2 13 *
Davidroid 0:5148e9486cf2 14 * Redistribution and use in source and binary forms, with or without modification,
Davidroid 0:5148e9486cf2 15 * are permitted provided that the following conditions are met:
Davidroid 0:5148e9486cf2 16 * 1. Redistributions of source code must retain the above copyright notice,
Davidroid 0:5148e9486cf2 17 * this list of conditions and the following disclaimer.
Davidroid 0:5148e9486cf2 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
Davidroid 0:5148e9486cf2 19 * this list of conditions and the following disclaimer in the documentation
Davidroid 0:5148e9486cf2 20 * and/or other materials provided with the distribution.
Davidroid 0:5148e9486cf2 21 * 3. Neither the name of STMicroelectronics nor the names of its contributors
Davidroid 0:5148e9486cf2 22 * may be used to endorse or promote products derived from this software
Davidroid 0:5148e9486cf2 23 * without specific prior written permission.
Davidroid 0:5148e9486cf2 24 *
Davidroid 0:5148e9486cf2 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Davidroid 0:5148e9486cf2 26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Davidroid 0:5148e9486cf2 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Davidroid 0:5148e9486cf2 28 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
Davidroid 0:5148e9486cf2 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Davidroid 0:5148e9486cf2 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Davidroid 0:5148e9486cf2 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Davidroid 0:5148e9486cf2 32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Davidroid 0:5148e9486cf2 33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Davidroid 0:5148e9486cf2 34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Davidroid 0:5148e9486cf2 35 *
Davidroid 0:5148e9486cf2 36 ******************************************************************************
Davidroid 0:5148e9486cf2 37 */
Davidroid 0:5148e9486cf2 38
Davidroid 0:5148e9486cf2 39
Davidroid 0:5148e9486cf2 40 /* Includes ------------------------------------------------------------------*/
Davidroid 0:5148e9486cf2 41
Davidroid 0:5148e9486cf2 42 /* mbed specific header files. */
Davidroid 0:5148e9486cf2 43 #include "mbed.h"
Davidroid 0:5148e9486cf2 44
Davidroid 0:5148e9486cf2 45 /* Helper header files. */
Davidroid 0:5148e9486cf2 46 #include "DevSPI.h"
Davidroid 0:5148e9486cf2 47
Davidroid 0:5148e9486cf2 48 /* Expansion Board specific header files. */
Davidroid 0:5148e9486cf2 49 #include "x_nucleo_ihm02a1_class.h"
Davidroid 0:5148e9486cf2 50
Davidroid 0:5148e9486cf2 51
Davidroid 0:5148e9486cf2 52 /* Definitions ---------------------------------------------------------------*/
Davidroid 0:5148e9486cf2 53
Davidroid 0:5148e9486cf2 54 /* Number of movements per revolution. */
Davidroid 0:5148e9486cf2 55 #define MPR_1 4
Davidroid 1:9f1974b0960d 56
Davidroid 1:9f1974b0960d 57 /* Number of steps. */
Davidroid 1:9f1974b0960d 58 #define STEPS_1 100000
Davidroid 1:9f1974b0960d 59 #define STEPS_2 200000
Davidroid 0:5148e9486cf2 60
Davidroid 0:5148e9486cf2 61 /* Delay in milliseconds. */
Davidroid 1:9f1974b0960d 62 #define DELAY_1 1000
Davidroid 0:5148e9486cf2 63 #define DELAY_2 2000
Davidroid 0:5148e9486cf2 64 #define DELAY_3 5000
Davidroid 0:5148e9486cf2 65
Davidroid 0:5148e9486cf2 66
Davidroid 0:5148e9486cf2 67 /* Variables -----------------------------------------------------------------*/
Davidroid 0:5148e9486cf2 68
Davidroid 0:5148e9486cf2 69 /* Motor Control Expansion Board. */
Davidroid 0:5148e9486cf2 70 X_NUCLEO_IHM02A1 *x_nucleo_ihm02a1;
Davidroid 0:5148e9486cf2 71
Davidroid 0:5148e9486cf2 72
Davidroid 0:5148e9486cf2 73 /* Main ----------------------------------------------------------------------*/
Davidroid 0:5148e9486cf2 74
Davidroid 0:5148e9486cf2 75 int main()
Davidroid 0:5148e9486cf2 76 {
Davidroid 1:9f1974b0960d 77 /*----- Initialization. -----*/
Davidroid 1:9f1974b0960d 78
Davidroid 0:5148e9486cf2 79
Davidroid 0:5148e9486cf2 80 /* Initializing SPI bus. */
Davidroid 0:5148e9486cf2 81 DevSPI dev_spi(D11, D12, D3);
Davidroid 0:5148e9486cf2 82
Davidroid 0:5148e9486cf2 83 /* Initializing Motor Control Expansion Board. */
Davidroid 1:9f1974b0960d 84 x_nucleo_ihm02a1 = X_NUCLEO_IHM02A1::Instance(A4, A5, D4, A2, &dev_spi);
Davidroid 0:5148e9486cf2 85
Davidroid 1:9f1974b0960d 86 /* Building a list of motor control components. */
Davidroid 1:9f1974b0960d 87 L6470 **motors = x_nucleo_ihm02a1->GetComponents();
Davidroid 0:5148e9486cf2 88
Davidroid 0:5148e9486cf2 89 /* Printing to the console. */
Davidroid 0:5148e9486cf2 90 printf("Motor Control Application Example for 2 Motors\r\n\n");
Davidroid 0:5148e9486cf2 91
Davidroid 1:9f1974b0960d 92
Davidroid 1:9f1974b0960d 93 /*----- Setting home and marke positions, getting positions, and going to positions. -----*/
Davidroid 1:9f1974b0960d 94
Davidroid 1:9f1974b0960d 95 /* Printing to the console. */
Davidroid 1:9f1974b0960d 96 printf("--> Setting home position.\r\n");
Davidroid 1:9f1974b0960d 97
Davidroid 1:9f1974b0960d 98 /* Setting the home position. */
Davidroid 1:9f1974b0960d 99 motors[0]->SetHome();
Davidroid 1:9f1974b0960d 100
Davidroid 1:9f1974b0960d 101 /* Waiting. */
Davidroid 1:9f1974b0960d 102 wait_ms(DELAY_1);
Davidroid 0:5148e9486cf2 103
Davidroid 1:9f1974b0960d 104 /* Getting the current position. */
Davidroid 1:9f1974b0960d 105 int position = motors[0]->GetPosition();
Davidroid 1:9f1974b0960d 106
Davidroid 1:9f1974b0960d 107 /* Printing to the console. */
Davidroid 1:9f1974b0960d 108 printf("--> Getting the current position: %d\r\n", position);
Davidroid 1:9f1974b0960d 109
Davidroid 1:9f1974b0960d 110 /* Waiting. */
Davidroid 1:9f1974b0960d 111 wait_ms(DELAY_1);
Davidroid 1:9f1974b0960d 112
Davidroid 1:9f1974b0960d 113 /* Printing to the console. */
Davidroid 1:9f1974b0960d 114 printf("--> Moving forward %d steps.\r\n", STEPS_1);
Davidroid 1:9f1974b0960d 115
Davidroid 1:9f1974b0960d 116 /* Moving. */
Davidroid 1:9f1974b0960d 117 motors[0]->Move(StepperMotor::FWD, STEPS_1);
Davidroid 0:5148e9486cf2 118
Davidroid 1:9f1974b0960d 119 /* Waiting while active. */
Davidroid 1:9f1974b0960d 120 motors[0]->WaitWhileActive();
Davidroid 1:9f1974b0960d 121
Davidroid 1:9f1974b0960d 122 /* Getting the current position. */
Davidroid 1:9f1974b0960d 123 position = motors[0]->GetPosition();
Davidroid 1:9f1974b0960d 124
Davidroid 1:9f1974b0960d 125 /* Printing to the console. */
Davidroid 1:9f1974b0960d 126 printf("--> Getting the current position: %d\r\n", position);
Davidroid 1:9f1974b0960d 127
Davidroid 1:9f1974b0960d 128 /* Printing to the console. */
Davidroid 1:9f1974b0960d 129 printf("--> Marking the current position.\r\n");
Davidroid 0:5148e9486cf2 130
Davidroid 1:9f1974b0960d 131 /* Marking the current position. */
Davidroid 1:9f1974b0960d 132 motors[0]->SetMark();
Davidroid 1:9f1974b0960d 133
Davidroid 1:9f1974b0960d 134 /* Waiting. */
Davidroid 1:9f1974b0960d 135 wait_ms(DELAY_1);
Davidroid 1:9f1974b0960d 136
Davidroid 1:9f1974b0960d 137 /* Printing to the console. */
Davidroid 1:9f1974b0960d 138 printf("--> Moving backward %d steps.\r\n", STEPS_2);
Davidroid 1:9f1974b0960d 139
Davidroid 1:9f1974b0960d 140 /* Moving. */
Davidroid 1:9f1974b0960d 141 motors[0]->Move(StepperMotor::BWD, STEPS_2);
Davidroid 1:9f1974b0960d 142
Davidroid 1:9f1974b0960d 143 /* Waiting while active. */
Davidroid 1:9f1974b0960d 144 motors[0]->WaitWhileActive();
Davidroid 0:5148e9486cf2 145
Davidroid 1:9f1974b0960d 146 /* Waiting. */
Davidroid 1:9f1974b0960d 147 wait_ms(DELAY_1);
Davidroid 1:9f1974b0960d 148
Davidroid 1:9f1974b0960d 149 /* Getting the current position. */
Davidroid 1:9f1974b0960d 150 position = motors[0]->GetPosition();
Davidroid 1:9f1974b0960d 151
Davidroid 1:9f1974b0960d 152 /* Printing to the console. */
Davidroid 1:9f1974b0960d 153 printf("--> Getting the current position: %d\r\n", position);
Davidroid 1:9f1974b0960d 154
Davidroid 1:9f1974b0960d 155 /* Waiting. */
Davidroid 1:9f1974b0960d 156 wait_ms(DELAY_1);
Davidroid 0:5148e9486cf2 157
Davidroid 1:9f1974b0960d 158 /* Printing to the console. */
Davidroid 1:9f1974b0960d 159 printf("--> Going to marked position.\r\n");
Davidroid 0:5148e9486cf2 160
Davidroid 1:9f1974b0960d 161 /* Going to marked position. */
Davidroid 1:9f1974b0960d 162 motors[0]->GoMark();
Davidroid 1:9f1974b0960d 163
Davidroid 1:9f1974b0960d 164 /* Waiting while active. */
Davidroid 1:9f1974b0960d 165 motors[0]->WaitWhileActive();
Davidroid 0:5148e9486cf2 166
Davidroid 1:9f1974b0960d 167 /* Waiting. */
Davidroid 1:9f1974b0960d 168 wait_ms(DELAY_1);
Davidroid 0:5148e9486cf2 169
Davidroid 1:9f1974b0960d 170 /* Getting the current position. */
Davidroid 1:9f1974b0960d 171 position = motors[0]->GetPosition();
Davidroid 1:9f1974b0960d 172
Davidroid 1:9f1974b0960d 173 /* Printing to the console. */
Davidroid 1:9f1974b0960d 174 printf("--> Getting the current position: %d\r\n", position);
Davidroid 0:5148e9486cf2 175
Davidroid 1:9f1974b0960d 176 /* Waiting. */
Davidroid 1:9f1974b0960d 177 wait_ms(DELAY_1);
Davidroid 1:9f1974b0960d 178
Davidroid 1:9f1974b0960d 179 /* Printing to the console. */
Davidroid 1:9f1974b0960d 180 printf("--> Going to home position.\r\n");
Davidroid 0:5148e9486cf2 181
Davidroid 1:9f1974b0960d 182 /* Going to home position. */
Davidroid 1:9f1974b0960d 183 motors[0]->GoHome();
Davidroid 1:9f1974b0960d 184
Davidroid 1:9f1974b0960d 185 /* Waiting while active. */
Davidroid 1:9f1974b0960d 186 motors[0]->WaitWhileActive();
Davidroid 1:9f1974b0960d 187
Davidroid 1:9f1974b0960d 188 /* Waiting. */
Davidroid 1:9f1974b0960d 189 wait_ms(DELAY_1);
Davidroid 0:5148e9486cf2 190
Davidroid 1:9f1974b0960d 191 /* Getting the current position. */
Davidroid 1:9f1974b0960d 192 position = motors[0]->GetPosition();
Davidroid 1:9f1974b0960d 193
Davidroid 1:9f1974b0960d 194 /* Printing to the console. */
Davidroid 1:9f1974b0960d 195 printf("--> Getting the current position: %d\r\n", position);
Davidroid 1:9f1974b0960d 196
Davidroid 1:9f1974b0960d 197 /* Waiting. */
Davidroid 1:9f1974b0960d 198 wait_ms(DELAY_2);
Davidroid 0:5148e9486cf2 199
Davidroid 0:5148e9486cf2 200
Davidroid 1:9f1974b0960d 201 /*----- Running together for a certain amount of time. -----*/
Davidroid 1:9f1974b0960d 202
Davidroid 1:9f1974b0960d 203 /* Printing to the console. */
Davidroid 1:9f1974b0960d 204 printf("--> Running together for %d seconds.\r\n", DELAY_3 / 1000);
Davidroid 0:5148e9486cf2 205
Davidroid 1:9f1974b0960d 206 /* Preparing each motor to perform a run at a specified speed. */
Davidroid 1:9f1974b0960d 207 for (int m = 0; m < L6470DAISYCHAINSIZE; m++)
Davidroid 1:9f1974b0960d 208 motors[m]->PrepareRun(StepperMotor::BWD, 400);
Davidroid 0:5148e9486cf2 209
Davidroid 1:9f1974b0960d 210 /* Performing the action on each motor at the same time. */
Davidroid 1:9f1974b0960d 211 x_nucleo_ihm02a1->PerformPreparedActions();
Davidroid 0:5148e9486cf2 212
Davidroid 1:9f1974b0960d 213 /* Waiting. */
Davidroid 1:9f1974b0960d 214 wait_ms(DELAY_3);
Davidroid 1:9f1974b0960d 215
Davidroid 1:9f1974b0960d 216
Davidroid 1:9f1974b0960d 217 /*----- Increasing the speed while running. -----*/
Davidroid 0:5148e9486cf2 218
Davidroid 1:9f1974b0960d 219 /* Preparing each motor to perform a run at a specified speed. */
Davidroid 1:9f1974b0960d 220 for (int m = 0; m < L6470DAISYCHAINSIZE; m++)
Davidroid 1:9f1974b0960d 221 motors[m]->PrepareGetSpeed();
Davidroid 0:5148e9486cf2 222
Davidroid 1:9f1974b0960d 223 /* Performing the action on each motor at the same time. */
Davidroid 1:9f1974b0960d 224 uint32_t* results = x_nucleo_ihm02a1->PerformPreparedActions();
Davidroid 0:5148e9486cf2 225
Davidroid 1:9f1974b0960d 226 /* Printing to the console. */
Davidroid 1:9f1974b0960d 227 printf(" Speed: M1 %d, M2 %d.\r\n", results[0], results[1]);
Davidroid 1:9f1974b0960d 228
Davidroid 1:9f1974b0960d 229 /* Printing to the console. */
Davidroid 1:9f1974b0960d 230 printf("--> Doublig the speed while running.\r\n");
Davidroid 0:5148e9486cf2 231
Davidroid 1:9f1974b0960d 232 /* Preparing each motor to perform a run at a specified speed. */
Davidroid 1:9f1974b0960d 233 for (int m = 0; m < L6470DAISYCHAINSIZE; m++)
Davidroid 1:9f1974b0960d 234 motors[m]->PrepareRun(StepperMotor::BWD, results[m] << 1);
Davidroid 1:9f1974b0960d 235
Davidroid 1:9f1974b0960d 236 /* Performing the action on each motor at the same time. */
Davidroid 1:9f1974b0960d 237 results = x_nucleo_ihm02a1->PerformPreparedActions();
Davidroid 0:5148e9486cf2 238
Davidroid 1:9f1974b0960d 239 /* Waiting. */
Davidroid 1:9f1974b0960d 240 wait_ms(DELAY_3);
Davidroid 0:5148e9486cf2 241
Davidroid 1:9f1974b0960d 242 /* Preparing each motor to perform a run at a specified speed. */
Davidroid 1:9f1974b0960d 243 for (int m = 0; m < L6470DAISYCHAINSIZE; m++)
Davidroid 1:9f1974b0960d 244 motors[m]->PrepareGetSpeed();
Davidroid 0:5148e9486cf2 245
Davidroid 1:9f1974b0960d 246 /* Performing the action on each motor at the same time. */
Davidroid 1:9f1974b0960d 247 results = x_nucleo_ihm02a1->PerformPreparedActions();
Davidroid 0:5148e9486cf2 248
Davidroid 1:9f1974b0960d 249 /* Printing to the console. */
Davidroid 1:9f1974b0960d 250 printf(" Speed: M1 %d, M2 %d.\r\n", results[0], results[1]);
Davidroid 1:9f1974b0960d 251
Davidroid 1:9f1974b0960d 252 /* Waiting. */
Davidroid 1:9f1974b0960d 253 wait_ms(DELAY_1);
Davidroid 0:5148e9486cf2 254
Davidroid 0:5148e9486cf2 255
Davidroid 1:9f1974b0960d 256 /*----- Hard Stop. -----*/
Davidroid 0:5148e9486cf2 257
Davidroid 1:9f1974b0960d 258 /* Printing to the console. */
Davidroid 1:9f1974b0960d 259 printf("--> Hard Stop.\r\n");
Davidroid 0:5148e9486cf2 260
Davidroid 1:9f1974b0960d 261 /* Preparing each motor to perform a hard stop. */
Davidroid 1:9f1974b0960d 262 for (int m = 0; m < L6470DAISYCHAINSIZE; m++)
Davidroid 1:9f1974b0960d 263 motors[m]->PrepareHardStop();
Davidroid 0:5148e9486cf2 264
Davidroid 1:9f1974b0960d 265 /* Performing the action on each motor at the same time. */
Davidroid 1:9f1974b0960d 266 x_nucleo_ihm02a1->PerformPreparedActions();
Davidroid 0:5148e9486cf2 267
Davidroid 1:9f1974b0960d 268 /* Waiting. */
Davidroid 1:9f1974b0960d 269 wait_ms(DELAY_2);
Davidroid 0:5148e9486cf2 270
Davidroid 0:5148e9486cf2 271
Davidroid 1:9f1974b0960d 272 /*----- Doing a full revolution on each motor, one after the other. -----*/
Davidroid 1:9f1974b0960d 273
Davidroid 1:9f1974b0960d 274 /* Printing to the console. */
Davidroid 1:9f1974b0960d 275 printf("--> Doing a full revolution on each motor, one after the other.\r\n");
Davidroid 1:9f1974b0960d 276
Davidroid 1:9f1974b0960d 277 /* Doing a full revolution on each motor, one after the other. */
Davidroid 1:9f1974b0960d 278 for (int m = 0; m < L6470DAISYCHAINSIZE; m++)
Davidroid 1:9f1974b0960d 279 for (int i = 0; i < MPR_1; i++)
Davidroid 1:9f1974b0960d 280 {
Davidroid 1:9f1974b0960d 281 /* Computing the number of steps. */
Davidroid 1:9f1974b0960d 282 int steps = (int) (((int) X_NUCLEO_IHM02A1::MotorParameterInitData[0][m].fullstepsperrevolution * pow(2.0f, X_NUCLEO_IHM02A1::MotorParameterInitData[0][m].step_sel)) / MPR_1);
Davidroid 1:9f1974b0960d 283
Davidroid 1:9f1974b0960d 284 /* Moving. */
Davidroid 1:9f1974b0960d 285 motors[m]->Move(StepperMotor::FWD, steps);
Davidroid 1:9f1974b0960d 286
Davidroid 1:9f1974b0960d 287 /* Waiting while active. */
Davidroid 1:9f1974b0960d 288 motors[m]->WaitWhileActive();
Davidroid 1:9f1974b0960d 289
Davidroid 1:9f1974b0960d 290 /* Waiting. */
Davidroid 1:9f1974b0960d 291 wait_ms(DELAY_1);
Davidroid 1:9f1974b0960d 292 }
Davidroid 1:9f1974b0960d 293
Davidroid 1:9f1974b0960d 294 /* Waiting. */
Davidroid 1:9f1974b0960d 295 wait_ms(DELAY_2);
Davidroid 1:9f1974b0960d 296
Davidroid 1:9f1974b0960d 297
Davidroid 1:9f1974b0960d 298 /*----- High Impedance State. -----*/
Davidroid 1:9f1974b0960d 299
Davidroid 1:9f1974b0960d 300 /* Printing to the console. */
Davidroid 1:9f1974b0960d 301 printf("--> High Impedance State.\r\n");
Davidroid 1:9f1974b0960d 302
Davidroid 1:9f1974b0960d 303 /* Preparing each motor to set High Impedance State. */
Davidroid 1:9f1974b0960d 304 for (int m = 0; m < L6470DAISYCHAINSIZE; m++)
Davidroid 1:9f1974b0960d 305 motors[m]->PrepareHardHiZ();
Davidroid 1:9f1974b0960d 306
Davidroid 1:9f1974b0960d 307 /* Performing the action on each motor at the same time. */
Davidroid 1:9f1974b0960d 308 x_nucleo_ihm02a1->PerformPreparedActions();
Davidroid 1:9f1974b0960d 309
Davidroid 1:9f1974b0960d 310 /* Waiting. */
Davidroid 1:9f1974b0960d 311 wait_ms(DELAY_2);
Davidroid 0:5148e9486cf2 312 }